This commit is contained in:
poma 2020-11-04 05:36:01 +03:00
parent 884c48899d
commit 3ef9f089ba
No known key found for this signature in database
GPG Key ID: BA20CB01FE165657
9 changed files with 116 additions and 74 deletions

View File

@ -1,3 +0,0 @@
RPC_URL=
INFURA_TOKEN=
PRIVATE_KEY=

View File

@ -12,20 +12,20 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
# - uses: actions/setup-node@v1
# with:
# node-version: 12
# - run: yarn install
# - run: yarn test
# - run: yarn lint
# - name: Telegram Failure Notification
# uses: appleboy/telegram-action@0.0.7
# if: failure()
# with:
# message: ❗ Build failed for [${{ github.repository }}](https://github.com/${{ github.repository }}/actions) because of ${{ github.actor }}
# format: markdown
# to: ${{ secrets.TELEGRAM_CHAT_ID }}
# token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
- uses: actions/setup-node@v1
with:
node-version: 12
- run: yarn install
- run: yarn test
- run: yarn lint
- name: Telegram Failure Notification
uses: appleboy/telegram-action@0.0.7
if: failure()
with:
message: ❗ Build failed for [${{ github.repository }}](https://github.com/${{ github.repository }}/actions) because of ${{ github.actor }}
format: markdown
to: ${{ secrets.TELEGRAM_CHAT_ID }}
token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
#
# publish:
# runs-on: ubuntu-latest

23
contracts/Deployer.sol Normal file
View File

@ -0,0 +1,23 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
interface IDeployer {
function deploy(bytes memory _initCode, bytes32 _salt) external returns (address payable createdContract);
}
contract Deployer {
IDeployer immutable deployer;
constructor(IDeployer _deployer) public {
// Use EIP-2470 SingletonFactory address by default
deployer = address(_deployer) == address(0) ? IDeployer(0xce0042B868300000d44A59004Da54A005ffdcf9f) : _deployer;
}
event Deployed(address indexed sender, address indexed addr);
function deploy(bytes memory _initCode, bytes32 _salt) external {
address createdContract = deployer.deploy(_initCode, _salt);
require(createdContract != address(0), "Deploy failed");
emit Deployed(msg.sender, createdContract);
}
}

View File

@ -1,11 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;
contract Echoer {
event Echo(address indexed who, bytes data);
function echo(bytes calldata data) external {
emit Echo(msg.sender, data);
}
}

View File

@ -0,0 +1,23 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
/**
* @title Singleton Factory (EIP-2470)
* @notice Exposes CREATE2 (EIP-1014) to deploy bytecode on deterministic addresses based on initialization code and salt.
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
*/
contract SingletonFactory {
/**
* @notice Deploys `_initCode` using `_salt` for defining the deterministic address.
* @param _initCode Initialization code.
* @param _salt Arbitrary value to modify resulting address.
* @return createdContract Created contract address.
*/
function deploy(bytes memory _initCode, bytes32 _salt) public returns (address payable createdContract) {
assembly {
createdContract := create2(0, add(_initCode, 0x20), mload(_initCode), _salt)
}
}
}
// IV is a value changed to generate the vanity address.
// IV: 6583047

View File

@ -1,10 +0,0 @@
/* global artifacts */
const Echoer = artifacts.require('Echoer')
module.exports = function (deployer) {
return deployer.then(async () => {
const echoer = await deployer.deploy(Echoer)
console.log('Echoer :', echoer.address)
})
}

View File

@ -10,10 +10,7 @@
"eslint": "eslint --ext .js --ignore-path .gitignore .",
"prettier:check": "prettier --check . --config .prettierrc",
"prettier:fix": "prettier --write . --config .prettierrc",
"lint": "yarn eslint && yarn prettier:check",
"deploy:mainnet": "truffle migrate --network mainnet",
"deploy:kovan": "truffle migrate --network kovan",
"deploy:dev": "truffle migrate --skip-dry-run --network development"
"lint": "yarn eslint && yarn prettier:check"
},
"repository": {
"type": "git",

55
test/deployer.test.js Normal file
View File

@ -0,0 +1,55 @@
/* global artifacts, web3, contract */
require('chai').use(require('bn-chai')(web3.utils.BN)).use(require('chai-as-promised')).should()
const { takeSnapshot, revertSnapshot } = require('../scripts/ganacheHelper')
const Deployer = artifacts.require('Deployer.sol')
const SingletonFactory = artifacts.require('SingletonFactory.sol')
const { keccak256, hexToBytes } = require('web3-utils')
function getExpectedAddress(address, bytecode, salt) {
const arg = hexToBytes('0xff')
.concat(hexToBytes(address))
.concat(hexToBytes(salt))
.concat(hexToBytes(keccak256(bytecode)))
return '0x' + keccak256(arg).slice(26)
}
contract('Deployer', (accounts) => {
let factory
let deployer
let snapshotId
before(async () => {
factory = await SingletonFactory.new()
deployer = await Deployer.new(factory.address)
snapshotId = await takeSnapshot()
})
describe('#deployer', () => {
it('should work', async () => {
const bytecode = SingletonFactory.bytecode
const salt = '0x000000000000000000000000000000000000000000000000000000000000beef'
const expectedAddress = getExpectedAddress(factory.address, bytecode, salt)
const { logs } = await deployer.deploy(bytecode, salt)
logs[0].event.should.be.equal('Deployed')
logs[0].args.sender.should.be.equal(accounts[0])
logs[0].args.addr.toLowerCase().should.be.equal(expectedAddress)
})
it('should throw on repeated deploy', async () => {
const bytecode = SingletonFactory.bytecode
const salt = '0x000000000000000000000000000000000000000000000000000000000000beef'
await deployer.deploy(bytecode, salt)
await deployer.deploy(bytecode, salt).should.be.rejectedWith('Deploy failed')
})
it('should throw on failed deploy')
})
afterEach(async () => {
await revertSnapshot(snapshotId.result)
// eslint-disable-next-line require-atomic-updates
snapshotId = await takeSnapshot()
})
})

View File

@ -1,32 +0,0 @@
/* global artifacts, web3, contract */
require('chai').use(require('bn-chai')(web3.utils.BN)).use(require('chai-as-promised')).should()
const { takeSnapshot, revertSnapshot } = require('../scripts/ganacheHelper')
const Echoer = artifacts.require('./Echoer.sol')
contract('Echoer', (accounts) => {
let echoer
let snapshotId
before(async () => {
echoer = await Echoer.deployed()
snapshotId = await takeSnapshot()
})
describe('#echo', () => {
it('should work', async () => {
const data = '0xbeef'
const { logs } = await echoer.echo(data)
logs[0].event.should.be.equal('Echo')
logs[0].args.who.should.be.equal(accounts[0])
logs[0].args.data.should.be.equal(data)
})
})
afterEach(async () => {
await revertSnapshot(snapshotId.result)
// eslint-disable-next-line require-atomic-updates
snapshotId = await takeSnapshot()
})
})