Contract Overview
Balance:
0 Ether
Token:
More Info
My Name Tag:
Not Available
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Similar Match Source Code
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0x0f75Dd5E00f0A153fCee92A1C242Dbdf32D87196
Contract Name:
GovernBaseFactory
Compiler Version
v0.6.8+commit.0bbfe453
Contract Source Code (Solidity Standard Json-Input format)
/* * SPDX-License-Identifier: GPL-3.0 */ pragma solidity 0.6.8; import "erc3k/contracts/IERC3000.sol"; import "@aragon/govern-core/contracts/Govern.sol"; import "@aragon/govern-contract-utils/contracts/minimal-proxies/ERC1167ProxyFactory.sol"; import "@aragon/govern-contract-utils/contracts/address-utils/AddressUtils.sol"; contract GovernFactory { using ERC1167ProxyFactory for address; using AddressUtils for address; address public base; constructor() public { setupBase(); } function newGovern(IERC3000 _initialExecutor, bytes32 _salt) public returns (Govern govern) { if (_salt != bytes32(0)) { return Govern(base.clone2(_salt, abi.encodeWithSelector(govern.initialize.selector, _initialExecutor)).toPayable()); } else { return new Govern(address(_initialExecutor)); } } function setupBase() private { base = address(new Govern(address(2))); } }
/* * SPDX-License-Identifier: MIT */ pragma solidity ^0.6.8; pragma experimental ABIEncoderV2; import "./ERC3000Data.sol"; abstract contract IERC3000 { /** * @notice Schedules an action for execution, allowing for challenges and vetos on a defined time window * @param container A Container struct holding both the payload being scheduled for execution and * the current configuration of the system * @return containerHash */ function schedule(ERC3000Data.Container memory container) virtual public returns (bytes32 containerHash); event Scheduled(bytes32 indexed containerHash, ERC3000Data.Payload payload); /** * @notice Executes an action after its execution delay has passed and its state hasn't been altered by a challenge or veto * @param container A ERC3000Data.Container struct holding both the payload being scheduled for execution and * the current configuration of the system * MUST be an ERC3000Executor call: payload.executor.exec(payload.actions) * @return failureMap * @return execResults */ function execute(ERC3000Data.Container memory container) virtual public returns (bytes32 failureMap, bytes[] memory execResults); event Executed(bytes32 indexed containerHash, address indexed actor); /** * @notice Challenge a container in case its scheduling is illegal as per Config.rules. Pulls collateral and dispute fees from sender into contract * @param container A ERC3000Data.Container struct holding both the payload being scheduled for execution and * the current configuration of the system * @param reason Hint for case reviewers as to why the scheduled container is illegal * @return resolverId */ function challenge(ERC3000Data.Container memory container, bytes memory reason) virtual public returns (uint256 resolverId); event Challenged(bytes32 indexed containerHash, address indexed actor, bytes reason, uint256 resolverId, ERC3000Data.Collateral collateral); /** * @notice Apply arbitrator's ruling over a challenge once it has come to a final ruling * @param container A ERC3000Data.Container struct holding both the payload being scheduled for execution and * the current configuration of the system * @param resolverId disputeId in the arbitrator in which the dispute over the container was created * @return failureMap * @return execResults */ function resolve(ERC3000Data.Container memory container, uint256 resolverId) virtual public returns (bytes32 failureMap, bytes[] memory execResults); event Resolved(bytes32 indexed containerHash, address indexed actor, bool approved); /** * @notice Apply arbitrator's ruling over a challenge once it has come to a final ruling * @param container A ERC3000Data.Container struct holding both the payload being scheduled for execution and * the current configuration of the system * @param reason Justification for the veto */ function veto(ERC3000Data.Container memory container, bytes memory reason) virtual public; event Vetoed(bytes32 indexed containerHash, address indexed actor, bytes reason); /** * @notice Apply a new configuration for all *new* containers to be scheduled * @param config A ERC3000Data.Config struct holding all the new params that will control the system * @return configHash */ function configure(ERC3000Data.Config memory config) virtual public returns (bytes32 configHash); event Configured(bytes32 indexed configHash, address indexed actor, ERC3000Data.Config config); }
/* * SPDX-License-Identifier: GPL-3.0 */ pragma solidity 0.6.8; pragma experimental ABIEncoderV2; import "erc3k/contracts/IERC3000Executor.sol"; import "erc3k/contracts/IERC3000.sol"; import "@aragon/govern-contract-utils/contracts/acl/ACL.sol"; import "@aragon/govern-contract-utils/contracts/adaptive-erc165/AdaptiveERC165.sol"; import "@aragon/govern-contract-utils/contracts/bitmaps/BitmapLib.sol"; import "@aragon/govern-contract-utils/contracts/address-utils/AddressUtils.sol"; import "@aragon/govern-contract-utils/contracts/erc20/ERC20.sol"; import "@aragon/govern-contract-utils/contracts/erc20/SafeERC20.sol"; import "./erc1271/ERC1271.sol"; contract Govern is IERC3000Executor, AdaptiveERC165, ERC1271, ACL { using BitmapLib for bytes32; using AddressUtils for address; using SafeERC20 for ERC20; string private constant ERROR_DEPOSIT_AMOUNT_ZERO = "GOVERN_DEPOSIT_AMOUNT_ZERO"; string private constant ERROR_ETH_DEPOSIT_AMOUNT_MISMATCH = "GOVERN_ETH_DEPOSIT_AMOUNT_MISMATCH"; string private constant ERROR_TOKEN_NOT_CONTRACT = "GOVERN_TOKEN_NOT_CONTRACT"; string private constant ERROR_TOKEN_DEPOSIT_FAILED = "GOVERN_TOKEN_DEPOSIT_FAILED"; string private constant ERROR_TOO_MANY_ACTIONS = "GOVERN_TOO_MANY_ACTIONS"; string private constant ERROR_ACTION_CALL_FAILED = "GOVERN_ACTION_CALL_FAILED"; string private constant ERROR_TOKEN_WITHDRAW_FAILED = "GOVERN_TOKEN_WITHDRAW_FAILED"; string private constant ERROR_ETH_WITHDRAW_FAILED = "GOVERN_ETH_WITHDRAW_FAILED"; bytes4 internal constant EXEC_ROLE = this.exec.selector; bytes4 internal constant WITHDRAW_ROLE = this.withdraw.selector; bytes4 internal constant REGISTER_STANDARD_ROLE = this.registerStandardAndCallback.selector; bytes4 internal constant SET_SIGNATURE_VALIDATOR_ROLE = this.setSignatureValidator.selector; uint256 internal constant MAX_ACTIONS = 256; ERC1271 signatureValidator; // ETHDeposited and Deposited are both needed. ETHDeposited makes sure that whoever sends funds // with `send/transfer`, receive function can still be executed without reverting due to gas cost // increases in EIP-2929. To still use `send/transfer`, access list is needed that has the address // of the contract(base contract) that is behind the proxy. event ETHDeposited(address sender, uint256 amount); event Deposited(address indexed sender, address indexed token, uint256 amount, string _reference); event Withdrawn(address indexed token, address indexed to, address from, uint256 amount, string _reference); constructor(address _initialExecutor) ACL(address(this)) public { initialize(_initialExecutor); } function initialize(address _initialExecutor) public initACL(address(this)) onlyInit("govern") { _grant(EXEC_ROLE, address(_initialExecutor)); _grant(WITHDRAW_ROLE, address(this)); // freeze the withdraw so that only GovernExecutor can call _freeze(WITHDRAW_ROLE); _grant(REGISTER_STANDARD_ROLE, address(this)); _grant(SET_SIGNATURE_VALIDATOR_ROLE, address(this)); _registerStandard(ERC3000_EXEC_INTERFACE_ID); _registerStandard(type(ERC1271).interfaceId); } receive () external payable { emit ETHDeposited(msg.sender, msg.value); } fallback () external { _handleCallback(msg.sig, msg.data); // WARN: does a low-level return, any code below would be unreacheable } function deposit(address _token, uint256 _amount, string calldata _reference) external payable { require(_amount > 0, ERROR_DEPOSIT_AMOUNT_ZERO); if (_token == address(0)) { require(msg.value == _amount, ERROR_ETH_DEPOSIT_AMOUNT_MISMATCH); } else { require(_token.isContract(), ERROR_TOKEN_NOT_CONTRACT); require(ERC20(_token).safeTransferFrom(msg.sender, address(this), _amount), ERROR_TOKEN_DEPOSIT_FAILED); } emit Deposited(msg.sender, _token, _amount, _reference); } function withdraw(address _token, address _from, address _to, uint256 _amount, string memory _reference) public auth(WITHDRAW_ROLE) { if (_token == address(0)) { (bool ok, ) = _to.call{value: _amount}(""); require(ok, ERROR_ETH_WITHDRAW_FAILED); } else { require(ERC20(_token).safeTransfer(_to, _amount), ERROR_TOKEN_WITHDRAW_FAILED); } emit Withdrawn(_token, _to, _from, _amount, _reference); } function exec(ERC3000Data.Action[] memory actions, bytes32 allowFailuresMap, bytes32 memo) override public auth(EXEC_ROLE) returns (bytes32, bytes[] memory) { require(actions.length <= MAX_ACTIONS, ERROR_TOO_MANY_ACTIONS); // need to limit since we use 256-bit bitmaps bytes[] memory execResults = new bytes[](actions.length); bytes32 failureMap = BitmapLib.empty; // start with an empty bitmap for (uint256 i = 0; i < actions.length; i++) { // TODO: optimize with assembly (bool ok, bytes memory ret) = actions[i].to.call{value: actions[i].value}(actions[i].data); require(ok || allowFailuresMap.get(uint8(i)), ERROR_ACTION_CALL_FAILED); // if a call fails, flip that bit to signal failure failureMap = ok ? failureMap : failureMap.flip(uint8(i)); execResults[i] = ret; } emit Executed(msg.sender, actions, memo, failureMap, execResults); return (failureMap, execResults); } function registerStandardAndCallback(bytes4 _interfaceId, bytes4 _callbackSig, bytes4 _magicNumber) external auth(REGISTER_STANDARD_ROLE) { _registerStandardAndCallback(_interfaceId, _callbackSig, _magicNumber); } function setSignatureValidator(ERC1271 _signatureValidator) external auth(SET_SIGNATURE_VALIDATOR_ROLE) { signatureValidator = _signatureValidator; } function isValidSignature(bytes32 _hash, bytes memory _signature) override public view returns (bytes4) { if (address(signatureValidator) == address(0)) return bytes4(0); // invalid magic number return signatureValidator.isValidSignature(_hash, _signature); // forward call to set validation contract } }
/* * SPDX-License-Identifier: MIT */ // Inspired by: https://github.com/optionality/clone-factory pragma solidity ^0.6.8; library ERC1167ProxyFactory { function clone(address _implementation) internal returns (address cloneAddr) { bytes memory createData = generateCreateData(_implementation); assembly { cloneAddr := create(0, add(createData, 0x20), 55) } require(cloneAddr != address(0), "proxy-factory: bad create"); } function clone(address _implementation, bytes memory _initData) internal returns (address cloneAddr) { cloneAddr = clone(_implementation); (bool ok, bytes memory ret) = cloneAddr.call(_initData); require(ok, _getRevertMsg(ret)); } function clone2(address _implementation, bytes32 _salt) internal returns (address cloneAddr) { bytes memory createData = generateCreateData(_implementation); assembly { cloneAddr := create2(0, add(createData, 0x20), 55, _salt) } require(cloneAddr != address(0), "proxy-factory: bad create2"); } function clone2(address _implementation, bytes32 _salt, bytes memory _initData) internal returns (address cloneAddr) { cloneAddr = clone2(_implementation, _salt); (bool ok, bytes memory ret) = cloneAddr.call(_initData); require(ok, _getRevertMsg(ret)); } function generateCreateData(address _implementation) internal pure returns (bytes memory) { return abi.encodePacked( //---- constructor ----- bytes10(0x3d602d80600a3d3981f3), //---- proxy code ----- bytes10(0x363d3d373d3d3d363d73), _implementation, bytes15(0x5af43d82803e903d91602b57fd5bf3) ); } // From: https://ethereum.stackexchange.com/a/83577 function _getRevertMsg(bytes memory _returnData) internal pure returns (string memory) { // If the _res length is less than 68, then the transaction failed silently (without a revert message) if (_returnData.length < 68) return ''; assembly { _returnData := add(_returnData, 0x04) // Slice the sighash. } return abi.decode(_returnData, (string)); // All that remains is the revert string } }
/* * SPDX-License-Identifier: MIT */ pragma solidity ^0.6.8; library AddressUtils { function toPayable(address addr) internal pure returns (address payable) { return address(bytes20(addr)); } /** * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed */ function isContract(address addr) internal view returns (bool result) { assembly { result := iszero(iszero(extcodesize(addr))) } } }
/* * SPDX-License-Identifier: MIT */ pragma solidity ^0.6.8; pragma experimental ABIEncoderV2; import "./IERC3000Executor.sol"; library ERC3000Data { // TODO: come up with a non-shitty name struct Container { Payload payload; Config config; } // WARN: Always remember to change the 'hash' function if modifying the struct struct Payload { uint256 nonce; uint256 executionTime; address submitter; IERC3000Executor executor; Action[] actions; bytes32 allowFailuresMap; bytes proof; } struct Action { address to; uint256 value; bytes data; } struct Config { uint256 executionDelay; // how many seconds to wait before being able to call `execute`. Collateral scheduleDeposit; // fees for scheduling Collateral challengeDeposit; // fees for challenging address resolver; // resolver that will rule the disputes bytes rules; // rules of how DAO should be managed uint256 maxCalldataSize; // max calldatasize for the schedule } struct Collateral { address token; uint256 amount; } function containerHash(bytes32 payloadHash, bytes32 configHash) internal view returns (bytes32) { uint chainId; assembly { chainId := chainid() } return keccak256(abi.encodePacked("erc3k-v1", address(this), chainId, payloadHash, configHash)); } function hash(Container memory container) internal view returns (bytes32) { return containerHash(hash(container.payload), hash(container.config)); } function hash(Payload memory payload) internal pure returns (bytes32) { return keccak256( abi.encode( payload.nonce, payload.executionTime, payload.submitter, payload.executor, keccak256(abi.encode(payload.actions)), payload.allowFailuresMap, keccak256(payload.proof) ) ); } function hash(Config memory config) internal pure returns (bytes32) { return keccak256(abi.encode(config)); } }
/* * SPDX-License-Identifier: MIT */ pragma solidity ^0.6.8; pragma experimental ABIEncoderV2; import "./ERC3000Data.sol"; abstract contract IERC3000Executor { bytes4 internal constant ERC3000_EXEC_INTERFACE_ID = this.exec.selector; /** * @notice Executes all given actions * @param actions A array of ERC3000Data.Action for later executing those * @param allowFailuresMap A map with the allowed failures * @param memo The hash of the ERC3000Data.Container * @return failureMap * @return execResults */ function exec(ERC3000Data.Action[] memory actions, bytes32 allowFailuresMap, bytes32 memo) virtual public returns (bytes32 failureMap, bytes[] memory execResults); event Executed(address indexed actor, ERC3000Data.Action[] actions, bytes32 memo, bytes32 failureMap, bytes[] execResults); }
/* * SPDX-License-Identifier: MIT */ pragma solidity ^0.6.8; pragma experimental ABIEncoderV2; import "../initializable/Initializable.sol"; import "./IACLOracle.sol"; library ACLData { enum BulkOp { Grant, Revoke, Freeze } struct BulkItem { BulkOp op; bytes4 role; address who; } } contract ACL is Initializable { bytes4 public constant ROOT_ROLE = this.grant.selector ^ this.revoke.selector ^ this.freeze.selector ^ this.bulk.selector ; // "Who" constants address internal constant ANY_ADDR = address(-1); // "Access" flags address internal constant UNSET_ROLE = address(0); address internal constant FREEZE_FLAG = address(1); // Also used as "who" address internal constant ALLOW_FLAG = address(2); // Role -> Who -> Access flag (unset or allow) or ACLOracle (any other address denominates auth via ACLOracle) mapping (bytes4 => mapping (address => address)) public roles; event Granted(bytes4 indexed role, address indexed actor, address indexed who, IACLOracle oracle); event Revoked(bytes4 indexed role, address indexed actor, address indexed who); event Frozen(bytes4 indexed role, address indexed actor); modifier auth(bytes4 _role) { require(willPerform(_role, msg.sender, msg.data), "acl: auth"); _; } modifier initACL(address _initialRoot) { // ACL might have been already initialized by constructors if (initBlocks["acl"] == 0) { _initializeACL(_initialRoot); } else { require(roles[ROOT_ROLE][_initialRoot] == ALLOW_FLAG, "acl: initial root misaligned"); } _; } constructor(address _initialRoot) public initACL(_initialRoot) { } function grant(bytes4 _role, address _who) external auth(ROOT_ROLE) { _grant(_role, _who); } function grantWithOracle(bytes4 _role, address _who, IACLOracle _oracle) external auth(ROOT_ROLE) { _grantWithOracle(_role, _who, _oracle); } function revoke(bytes4 _role, address _who) external auth(ROOT_ROLE) { _revoke(_role, _who); } function freeze(bytes4 _role) external auth(ROOT_ROLE) { _freeze(_role); } function bulk(ACLData.BulkItem[] calldata items) external auth(ROOT_ROLE) { for (uint256 i = 0; i < items.length; i++) { ACLData.BulkItem memory item = items[i]; if (item.op == ACLData.BulkOp.Grant) _grant(item.role, item.who); else if (item.op == ACLData.BulkOp.Revoke) _revoke(item.role, item.who); else if (item.op == ACLData.BulkOp.Freeze) _freeze(item.role); } } function willPerform(bytes4 _role, address _who, bytes memory _data) internal returns (bool) { // First check if the given who is auth'd, then if any address is auth'd return _checkRole(_role, _who, _data) || _checkRole(_role, ANY_ADDR, _data); } function isFrozen(bytes4 _role) public view returns (bool) { return roles[_role][FREEZE_FLAG] == FREEZE_FLAG; } function _initializeACL(address _initialRoot) internal onlyInit("acl") { _grant(ROOT_ROLE, _initialRoot); } function _grant(bytes4 _role, address _who) internal { _grantWithOracle(_role, _who, IACLOracle(ALLOW_FLAG)); } function _grantWithOracle(bytes4 _role, address _who, IACLOracle _oracle) internal { require(!isFrozen(_role), "acl: frozen"); require(_who != FREEZE_FLAG, "acl: bad freeze"); roles[_role][_who] = address(_oracle); emit Granted(_role, msg.sender, _who, _oracle); } function _revoke(bytes4 _role, address _who) internal { require(!isFrozen(_role), "acl: frozen"); roles[_role][_who] = UNSET_ROLE; emit Revoked(_role, msg.sender, _who); } function _freeze(bytes4 _role) internal { require(!isFrozen(_role), "acl: frozen"); roles[_role][FREEZE_FLAG] = FREEZE_FLAG; emit Frozen(_role, msg.sender); } function _checkRole(bytes4 _role, address _who, bytes memory _data) internal returns (bool) { address accessFlagOrAclOracle = roles[_role][_who]; if (accessFlagOrAclOracle != UNSET_ROLE) { if (accessFlagOrAclOracle == ALLOW_FLAG) return true; // Since it's not a flag, assume it's an ACLOracle and try-catch to skip failures try IACLOracle(accessFlagOrAclOracle).willPerform(_role, _who, _data) returns (bool allowed) { if (allowed) return true; } catch { } } return false; } }
/* * SPDX-License-Identifier: MIT */ pragma solidity ^0.6.8; import "../erc165/ERC165.sol"; contract AdaptiveERC165 is ERC165 { // ERC165 interface ID -> whether it is supported mapping (bytes4 => bool) internal standardSupported; // Callback function signature -> magic number to return mapping (bytes4 => bytes32) internal callbackMagicNumbers; bytes32 internal constant UNREGISTERED_CALLBACK = bytes32(0); event RegisteredStandard(bytes4 interfaceId); event RegisteredCallback(bytes4 sig, bytes4 magicNumber); event ReceivedCallback(bytes4 indexed sig, bytes data); function supportsInterface(bytes4 _interfaceId) override virtual public view returns (bool) { return standardSupported[_interfaceId] || super.supportsInterface(_interfaceId); } function _handleCallback(bytes4 _sig, bytes memory _data) internal { bytes32 magicNumber = callbackMagicNumbers[_sig]; require(magicNumber != UNREGISTERED_CALLBACK, "adap-erc165: unknown callback"); emit ReceivedCallback(_sig, _data); // low-level return magic number assembly { mstore(0x00, magicNumber) return(0x00, 0x20) } } function _registerStandardAndCallback(bytes4 _interfaceId, bytes4 _callbackSig, bytes4 _magicNumber) internal { _registerStandard(_interfaceId); _registerCallback(_callbackSig, _magicNumber); } function _registerStandard(bytes4 _interfaceId) internal { standardSupported[_interfaceId] = true; emit RegisteredStandard(_interfaceId); } function _registerCallback(bytes4 _callbackSig, bytes4 _magicNumber) internal { callbackMagicNumbers[_callbackSig] = _magicNumber; emit RegisteredCallback(_callbackSig, _magicNumber); } }
/* * SPDX-License-Identifier: MIT */ pragma solidity ^0.6.8; library BitmapLib { bytes32 constant internal empty = bytes32(0); function flip(bytes32 map, uint8 index) internal pure returns (bytes32) { return bytes32(uint256(map) ^ uint256(1) << index); } function get(bytes32 map, uint8 index) internal pure returns (bool) { return (uint256(map) >> index & 1) == 1; } }
/* * SPDX-License-Identifier: MIT */ pragma solidity ^0.6.8; /** * @title ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 */ interface ERC20 { // Optional fields function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function totalSupply() external view returns (uint256); function balanceOf(address _who) external view returns (uint256); function allowance(address _owner, address _spender) external view returns (uint256); function transfer(address _to, uint256 _value) external returns (bool); function approve(address _spender, uint256 _value) external returns (bool); function transferFrom(address _from, address _to, uint256 _value) external returns (bool); event Transfer( address indexed from, address indexed to, uint256 value ); event Approval( address indexed owner, address indexed spender, uint256 value ); }
/* * SPDX-License-Identifier: MIT */ // From https://github.com/aragon/aragonOS/blob/next/contracts/common/SafeERC20.sol // Inspired by AdEx (https://github.com/AdExNetwork/adex-protocol-eth/blob/b9df617829661a7518ee10f4cb6c4108659dd6d5/contracts/libs/SafeERC20.sol) // and 0x (https://github.com/0xProject/0x-monorepo/blob/737d1dc54d72872e24abce5a1dbe1b66d35fa21a/contracts/protocol/contracts/protocol/AssetProxy/ERC20Proxy.sol#L143) pragma solidity ^0.6.8; import "../address-utils/AddressUtils.sol"; import "./ERC20.sol"; library SafeERC20 { using AddressUtils for address; function invokeAndCheckSuccess(address _addr, bytes memory _calldata) private returns (bool ret) { if (!_addr.isContract()) { return false; } assembly { let ptr := mload(0x40) // free memory pointer let success := call( gas(), // forward all _addr, // address 0, // no value add(_calldata, 0x20), // calldata start mload(_calldata), // calldata length ptr, // write output over free memory 0x20 // uint256 return ) if gt(success, 0) { // Check number of bytes returned from last function call switch returndatasize() // No bytes returned: assume success case 0 { ret := 1 } // 32 bytes returned: check if non-zero case 0x20 { // Only return success if returned data was true // Already have output in ptr ret := iszero(iszero(mload(ptr))) } // Not sure what was returned: don't mark as success default { } } } } /** * @dev Same as a standards-compliant ERC20.transfer() that never reverts (returns false). * Note that this makes an external call to the token. */ function safeTransfer(ERC20 _token, address _to, uint256 _amount) internal returns (bool) { bytes memory transferCallData = abi.encodeWithSelector( _token.transfer.selector, _to, _amount ); return invokeAndCheckSuccess(address(_token), transferCallData); } /** * @dev Same as a standards-compliant ERC20.transferFrom() that never reverts (returns false). * Note that this makes an external call to the token. */ function safeTransferFrom(ERC20 _token, address _from, address _to, uint256 _amount) internal returns (bool) { bytes memory transferFromCallData = abi.encodeWithSelector( _token.transferFrom.selector, _from, _to, _amount ); return invokeAndCheckSuccess(address(_token), transferFromCallData); } /** * @dev Same as a standards-compliant ERC20.approve() that never reverts (returns false). * Note that this makes an external call to the token. */ function safeApprove(ERC20 _token, address _spender, uint256 _amount) internal returns (bool) { bytes memory approveCallData = abi.encodeWithSelector( _token.approve.selector, _spender, _amount ); return invokeAndCheckSuccess(address(_token), approveCallData); } }
/* * SPDX-License-Identifier: MIT */ pragma solidity ^0.6.8; /** * @title ERC1271 interface * @dev see https://eips.ethereum.org/EIPS/eip-1271 */ abstract contract ERC1271 { // bytes4(keccak256("isValidSignature(bytes32,bytes)") bytes4 constant internal MAGICVALUE = 0x1626ba7e; /** * @dev Should return whether the signature provided is valid for the provided data * @param _hash Keccak256 hash of arbitrary length data signed on the behalf of address(this) * @param _signature Signature byte array associated with _data * * MUST return the bytes4 magic value 0x1626ba7e when function passes. * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5) * MUST allow external calls */ function isValidSignature(bytes32 _hash, bytes memory _signature) virtual public view returns (bytes4 magicValue); }
/* * SPDX-License-Identifier: MIT */ pragma solidity 0.6.8; contract Initializable { mapping (string => uint256) public initBlocks; event Initialized(string indexed key); modifier onlyInit(string memory key) { require(initBlocks[key] == 0, "initializable: already initialized"); initBlocks[key] = block.number; _; emit Initialized(key); } }
/* * SPDX-License-Identifier: MIT */ pragma solidity ^0.6.8; interface IACLOracle { function willPerform(bytes4 role, address who, bytes calldata data) external returns (bool allowed); }
/* * SPDX-License-Identifier: MIT */ pragma solidity ^0.6.8; abstract contract ERC165 { // Includes supportsInterface method: bytes4 internal constant ERC165_INTERFACE_ID = bytes4(0x01ffc9a7); /** * @dev Query if a contract implements a certain interface * @param _interfaceId The interface identifier being queried, as specified in ERC-165 * @return True if the contract implements the requested interface and if its not 0xffffffff, false otherwise */ function supportsInterface(bytes4 _interfaceId) virtual public view returns (bool) { return _interfaceId == ERC165_INTERFACE_ID; } }
/* * SPDX-License-Identifier: GPL-3.0 */ pragma solidity 0.6.8; pragma experimental ABIEncoderV2; import "@aragon/govern-core/contracts/GovernRegistry.sol"; import "@aragon/govern-token/contracts/GovernTokenFactory.sol"; import "@aragon/govern-token/contracts/interfaces/IERC20.sol"; import "@aragon/govern-token/contracts/GovernMinter.sol"; import "@aragon/govern-token/contracts/libraries/TokenLib.sol"; import "./core-factories/GovernFactory.sol"; import "./core-factories/GovernQueueFactory.sol"; contract GovernBaseFactory { address internal constant ANY_ADDR = address(-1); uint256 internal constant MAX_SCHEDULE_ACCESS_LIST_ALLOWED = 10; string private constant ERROR_SCHEDULE_LIST_EXCEEDED = "basefactory: schedule list exceeded"; GovernFactory public governFactory; GovernQueueFactory public queueFactory; GovernTokenFactory public tokenFactory; GovernRegistry public registry; constructor( GovernRegistry _registry, GovernFactory _governFactory, GovernQueueFactory _queueFactory, GovernTokenFactory _tokenFactory ) public { governFactory = _governFactory; queueFactory = _queueFactory; tokenFactory = _tokenFactory; registry = _registry; } function newGovern( TokenLib.TokenConfig calldata _token, address[] calldata _scheduleAccessList, bool _useProxies, ERC3000Data.Config calldata _config, string calldata _name ) external returns (Govern govern, GovernQueue queue) { require(_scheduleAccessList.length <= MAX_SCHEDULE_ACCESS_LIST_ALLOWED, ERROR_SCHEDULE_LIST_EXCEEDED); bytes32 salt = _useProxies ? keccak256(abi.encodePacked(_name)) : bytes32(0); queue = queueFactory.newQueue(address(this), _config, salt); govern = governFactory.newGovern(queue, salt); IERC20 token = _token.tokenAddress; GovernMinter minter; if (address(token) == address(0)) { (token, minter) = tokenFactory.newToken( govern, _token, _useProxies ); // if both(scheduleDeposit and challengeDeposit) are non-zero, // they have already been set and no need for a config change. if (_config.scheduleDeposit.token == address(0) || _config.challengeDeposit.token == address(0)) { // give base factory the permission so that it can change // the config with new token in the same transaction queue.grant(queue.configure.selector, address(this)); ERC3000Data.Config memory newConfig = ERC3000Data.Config({ executionDelay: _config.executionDelay, scheduleDeposit: ERC3000Data.Collateral({ token: _config.scheduleDeposit.token != address(0) ? _config.scheduleDeposit.token : address(token), amount: _config.scheduleDeposit.amount }), challengeDeposit: ERC3000Data.Collateral({ token: _config.challengeDeposit.token != address(0) ? _config.challengeDeposit.token : address(token), amount: _config.challengeDeposit.amount }), resolver: _config.resolver, rules: _config.rules, maxCalldataSize: _config.maxCalldataSize }); queue.configure(newConfig); queue.revoke(queue.configure.selector, address(this)); } } registry.register(govern, queue, token, address(minter), _name, ""); uint256 bulkSize = _scheduleAccessList.length == 0 ? 7 : 6 + _scheduleAccessList.length; ACLData.BulkItem[] memory items = new ACLData.BulkItem[](bulkSize); items[0] = ACLData.BulkItem(ACLData.BulkOp.Grant, queue.execute.selector, ANY_ADDR); items[1] = ACLData.BulkItem(ACLData.BulkOp.Grant, queue.challenge.selector, ANY_ADDR); items[2] = ACLData.BulkItem(ACLData.BulkOp.Grant, queue.configure.selector, address(govern)); items[3] = ACLData.BulkItem(ACLData.BulkOp.Revoke, queue.ROOT_ROLE(), address(this)); items[4] = ACLData.BulkItem(ACLData.BulkOp.Grant, queue.ROOT_ROLE(), address(govern)); items[5] = ACLData.BulkItem(ACLData.BulkOp.Freeze, queue.ROOT_ROLE(), address(0)); // If the schedule access list is empty, anyone can schedule // otherwise, only the addresses specified are allowed. if (_scheduleAccessList.length == 0) { items[6] = ACLData.BulkItem(ACLData.BulkOp.Grant, queue.schedule.selector, ANY_ADDR); } else { for (uint256 i = 0; i < _scheduleAccessList.length; i++) { items[6 + i] = ACLData.BulkItem( ACLData.BulkOp.Grant, queue.schedule.selector, _scheduleAccessList[i] ); } } queue.bulk(items); } }
/* * SPDX-License-Identifier: GPL-3.0 */ pragma solidity 0.6.8; import "erc3k/contracts/IERC3000.sol"; import "erc3k/contracts/IERC3000Executor.sol"; import "erc3k/contracts/IERC3000Registry.sol"; import "@aragon/govern-contract-utils/contracts/erc165/ERC165.sol"; contract GovernRegistry is IERC3000Registry { mapping(string => bool) public nameUsed; function register( IERC3000Executor _executor, IERC3000 _queue, IERC20 _token, address minter, string calldata _name, bytes calldata _initialMetadata ) override external { require(!nameUsed[_name], "registry: name used"); nameUsed[_name] = true; emit Registered(_executor, _queue, _token, minter, msg.sender, _name); _setMetadata(_executor, _initialMetadata); } function setMetadata(bytes memory _metadata) override public { _setMetadata(IERC3000Executor(msg.sender), _metadata); } function _setMetadata(IERC3000Executor _executor, bytes memory _metadata) internal { emit SetMetadata(_executor, _metadata); } }
/* * SPDX-License-Identifier: GPL-3.0 */ pragma solidity 0.6.8; pragma experimental ABIEncoderV2; import "@aragon/govern-contract-utils/contracts/minimal-proxies/ERC1167ProxyFactory.sol"; import "./libraries/TokenLib.sol"; import "erc3k/contracts/IERC3000Executor.sol"; import "./GovernToken.sol"; import "./GovernMinter.sol"; import "./MerkleDistributor.sol"; contract GovernTokenFactory { using ERC1167ProxyFactory for address; address public tokenBase; address public minterBase; address public distributorBase; event CreatedToken(GovernToken token, GovernMinter minter); constructor() public { setupBases(); } function newToken( IERC3000Executor _governExecutor, TokenLib.TokenConfig calldata _token, bool _useProxies ) external returns ( GovernToken token, GovernMinter minter ) { if (!_useProxies) { (token, minter) = _deployContracts(_token.tokenName, _token.tokenSymbol, _token.tokenDecimals); } else { token = GovernToken(tokenBase.clone(abi.encodeWithSelector( token.initialize.selector, address(this), _token.tokenName, _token.tokenSymbol, _token.tokenDecimals ))); minter = GovernMinter(minterBase.clone(abi.encodeWithSelector( minter.initialize.selector, token, address(this), MerkleDistributor(distributorBase) ))); } token.changeMinter(address(minter)); if (_token.mintAmount > 0) { minter.mint(_token.mintAddress, _token.mintAmount, "initial mint"); } if (_token.merkleRoot != bytes32(0)) { minter.merkleMint(_token.merkleRoot, _token.merkleMintAmount, _token.merkleTree, _token.merkleContext); } bytes4 mintRole = minter.mint.selector ^ minter.merkleMint.selector; bytes4 rootRole = minter.ROOT_ROLE(); ACLData.BulkItem[] memory items = new ACLData.BulkItem[](4); items[0] = ACLData.BulkItem(ACLData.BulkOp.Grant, mintRole, address(_governExecutor)); items[1] = ACLData.BulkItem(ACLData.BulkOp.Grant, rootRole, address(_governExecutor)); items[2] = ACLData.BulkItem(ACLData.BulkOp.Revoke, mintRole, address(this)); items[3] = ACLData.BulkItem(ACLData.BulkOp.Revoke, rootRole, address(this)); minter.bulk(items); emit CreatedToken(token, minter); } function setupBases() private { distributorBase = address(new MerkleDistributor(ERC20(tokenBase), bytes32(0))); (GovernToken token, GovernMinter minter) = _deployContracts( "GovernToken base", "GTB", 0 ); token.changeMinter(address(minter)); // test the bases minter.mint(msg.sender, 1, "test mint"); minter.merkleMint(bytes32(0), 1, "no tree", "test merkle mint"); // store bases tokenBase = address(token); minterBase = address(minter); } function _deployContracts( string memory _tokenName, string memory _tokenSymbol, uint8 _tokenDecimals ) internal returns ( GovernToken token, GovernMinter minter ) { token = new GovernToken(address(this), _tokenName, _tokenSymbol, _tokenDecimals); minter = new GovernMinter(GovernToken(token), address(this), MerkleDistributor(distributorBase)); } }
/* * SPDX-License-Identifier: GPL-3.0 */ pragma solidity ^0.6.8; interface IERC20 { function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transfer(address recipient, uint256 amount) external returns (bool); function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); }
/* * SPDX-License-Identifier: GPL-3.0 */ pragma solidity ^0.6.8; pragma experimental ABIEncoderV2; import "@aragon/govern-contract-utils/contracts/acl/ACL.sol"; import "@aragon/govern-contract-utils/contracts/minimal-proxies/ERC1167ProxyFactory.sol"; import "./GovernToken.sol"; import "./MerkleDistributor.sol"; contract GovernMinter is ACL { using ERC1167ProxyFactory for address; bytes4 constant internal MINT_ROLE = this.mint.selector ^ this.merkleMint.selector ; GovernToken public token; address public distributorBase; event MintedSingle(address indexed to, uint256 amount, bytes context); event MintedMerkle(address indexed distributor, bytes32 indexed merkleRoot, uint256 totalAmount, bytes tree, bytes context); constructor(GovernToken _token, address _initialMinter, MerkleDistributor _distributorBase) ACL(_initialMinter) public { initialize(_token, _initialMinter, _distributorBase); } function initialize(GovernToken _token, address _initialMinter, MerkleDistributor _distributorBase) public initACL(_initialMinter) onlyInit("minter") { token = _token; distributorBase = address(_distributorBase); _grant(MINT_ROLE, _initialMinter); } function mint(address _to, uint256 _amount, bytes calldata _context) external auth(MINT_ROLE) { token.mint(_to, _amount); emit MintedSingle(_to, _amount, _context); } function merkleMint(bytes32 _merkleRoot, uint256 _totalAmount, bytes calldata _tree, bytes calldata _context) external auth(MINT_ROLE) returns (MerkleDistributor distributor) { address distributorAddr = distributorBase.clone(abi.encodeWithSelector(distributor.initialize.selector, token, _merkleRoot)); token.mint(distributorAddr, _totalAmount); emit MintedMerkle(distributorAddr, _merkleRoot, _totalAmount, _tree, _context); return MerkleDistributor(distributorAddr); } function eject(address _newMinter) external auth(this.eject.selector) { token.changeMinter(_newMinter); } }
/* * SPDX-License-Identifier: MIT */ pragma solidity ^0.6.8; import "../interfaces/IERC20.sol"; library TokenLib { struct TokenConfig { IERC20 tokenAddress; uint8 tokenDecimals; string tokenName; string tokenSymbol; address mintAddress; // initial minter address uint256 mintAmount; // how much to mint to initial minter address // merkle settings bytes32 merkleRoot; // merkle distribution root. uint256 merkleMintAmount; // how much to mint for the distributor. bytes merkleTree; // merkle tree object bytes merkleContext; // context/string what's the actual reason is... } }
/* * SPDX-License-Identifier: GPL-3.0 */ pragma solidity 0.6.8; pragma experimental ABIEncoderV2; import "@aragon/govern-core/contracts/pipelines/GovernQueue.sol"; import "@aragon/govern-contract-utils/contracts/minimal-proxies/ERC1167ProxyFactory.sol"; contract GovernQueueFactory { using ERC1167ProxyFactory for address; address public base; constructor() public { setupBase(); } function newQueue(address _aclRoot, ERC3000Data.Config memory _config, bytes32 _salt) public returns (GovernQueue queue) { if (_salt != bytes32(0)) { return GovernQueue(base.clone2(_salt, abi.encodeWithSelector(queue.initialize.selector, _aclRoot, _config))); } else { return new GovernQueue(_aclRoot, _config); } } function setupBase() private { ERC3000Data.Collateral memory noCollateral; ERC3000Data.Config memory config = ERC3000Data.Config( 3600, // how many seconds to wait before being able to call `execute` noCollateral, noCollateral, address(0), "", 100000 // initial maxCalldatasize ); base = address(new GovernQueue(address(2), config)); } }
/* * SPDX-License-Identifier: MIT */ pragma solidity 0.6.8; import "./IERC3000.sol"; import "./IERC3000Executor.sol"; import "@aragon/govern-token/contracts/interfaces/IERC20.sol"; abstract contract IERC3000Registry { /** * @notice Registers a IERC3000Executor and IERC3000 contract by a name and with his metadata * @param executor IERC3000Executor contract * @param queue IERC3000 contract * @param name The name of this DAO * @param token Governance token of the DAO * @param initialMetadata Additional data to store for this DAO */ function register(IERC3000Executor executor, IERC3000 queue, IERC20 token, address minter, string calldata name, bytes calldata initialMetadata) virtual external; event Registered(IERC3000Executor indexed executor, IERC3000 queue, IERC20 indexed token, address minter, address indexed registrant, string name); /** * @notice Sets or updates the metadata of a DAO * @param metadata Additional data to store for this DAO */ function setMetadata(bytes memory metadata) virtual public; event SetMetadata(IERC3000Executor indexed executor, bytes metadata); }
/* * SPDX-License-Identifier: GPL-3.0 */ pragma solidity ^0.6.8; import '@aragon/govern-contract-utils/contracts/initializable/Initializable.sol'; import '@aragon/govern-contract-utils/contracts/safe-math/SafeMath.sol'; import './interfaces/IERC20.sol'; // Copied and slightly modified from https://github.com/aragon/aragon-network-token/blob/v2-v1.0.0/packages/v2/contracts/token.sol // Lightweight token modelled after UNI-LP: https://github.com/Uniswap/uniswap-v2-core/blob/v1.0.1/contracts/UniswapV2ERC20.sol // Adds: // - An exposed `mint()` with minting role // - An exposed `burn()` // - ERC-3009 (`transferWithAuthorization()`) contract GovernToken is IERC20, Initializable { using SafeMath for uint256; // bytes32 private constant EIP712DOMAIN_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)") bytes32 private constant EIP712DOMAIN_HASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f; // bytes32 private constant VERSION_HASH = keccak256("1") bytes32 private constant VERSION_HASH = 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6; // bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; // bytes32 public constant TRANSFER_WITH_AUTHORIZATION_TYPEHASH = // keccak256("TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)"); bytes32 public constant TRANSFER_WITH_AUTHORIZATION_TYPEHASH = 0x7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a2267; string public name; string public symbol; uint8 public decimals; address public minter; uint256 override public totalSupply; mapping (address => uint256) override public balanceOf; mapping (address => mapping (address => uint256)) override public allowance; // ERC-2612, ERC-3009 state mapping (address => uint256) public nonces; mapping (address => mapping (bytes32 => bool)) public authorizationState; event Approval(address indexed owner, address indexed spender, uint256 value); event Transfer(address indexed from, address indexed to, uint256 value); event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce); event ChangeMinter(address indexed minter); modifier onlyMinter { require(msg.sender == minter, "token: not minter"); _; } constructor(address _initialMinter, string memory _name, string memory _symbol, uint8 _decimals) public { initialize(_initialMinter, _name, _symbol, _decimals); } function initialize(address _initialMinter, string memory _name, string memory _symbol, uint8 _decimals) public onlyInit("token") { _changeMinter(_initialMinter); name = _name; symbol = _symbol; decimals = _decimals; } function _validateSignedData(address signer, bytes32 encodeData, uint8 v, bytes32 r, bytes32 s) internal view { bytes32 digest = keccak256( abi.encodePacked( "\x19\x01", getDomainSeparator(), encodeData ) ); address recoveredAddress = ecrecover(digest, v, r, s); // Explicitly disallow authorizations for address(0) as ecrecover returns address(0) on malformed messages require(recoveredAddress != address(0) && recoveredAddress == signer, "token: bad sig"); } function _changeMinter(address newMinter) internal { minter = newMinter; emit ChangeMinter(newMinter); } function _mint(address to, uint256 value) internal { totalSupply = totalSupply.add(value); balanceOf[to] = balanceOf[to].add(value); emit Transfer(address(0), to, value); } function _burn(address from, uint value) internal { // Balance is implicitly checked with SafeMath's underflow protection balanceOf[from] = balanceOf[from].sub(value); totalSupply = totalSupply.sub(value); emit Transfer(from, address(0), value); } function _approve(address owner, address spender, uint256 value) private { allowance[owner][spender] = value; emit Approval(owner, spender, value); } function _transfer(address from, address to, uint256 value) private { require(to != address(this) && to != address(0), "token: bad to"); // Balance is implicitly checked with SafeMath's underflow protection balanceOf[from] = balanceOf[from].sub(value); balanceOf[to] = balanceOf[to].add(value); emit Transfer(from, to, value); } function getChainId() public pure returns (uint256 chainId) { assembly { chainId := chainid() } } function getDomainSeparator() public view returns (bytes32) { return keccak256( abi.encode( EIP712DOMAIN_HASH, keccak256(abi.encodePacked(name)), VERSION_HASH, getChainId(), address(this) ) ); } function mint(address to, uint256 value) external onlyMinter returns (bool) { _mint(to, value); return true; } function changeMinter(address newMinter) external onlyMinter { _changeMinter(newMinter); } function burn(uint256 value) external returns (bool) { _burn(msg.sender, value); return true; } function approve(address spender, uint256 value) override external returns (bool) { _approve(msg.sender, spender, value); return true; } function transfer(address to, uint256 value) override external returns (bool) { _transfer(msg.sender, to, value); return true; } function transferFrom(address from, address to, uint256 value) override external returns (bool) { uint256 fromAllowance = allowance[from][msg.sender]; if (fromAllowance != uint256(-1)) { // Allowance is implicitly checked with SafeMath's underflow protection allowance[from][msg.sender] = fromAllowance.sub(value); } _transfer(from, to, value); return true; } function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external { require(deadline >= block.timestamp, "token: auth expired"); bytes32 encodeData = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline)); _validateSignedData(owner, encodeData, v, r, s); _approve(owner, spender, value); } function transferWithAuthorization( address from, address to, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s ) external { require(block.timestamp > validAfter, "token: auth wait"); require(block.timestamp < validBefore, "token: auth expired"); require(!authorizationState[from][nonce], "token: auth used"); bytes32 encodeData = keccak256(abi.encode(TRANSFER_WITH_AUTHORIZATION_TYPEHASH, from, to, value, validAfter, validBefore, nonce)); _validateSignedData(from, encodeData, v, r, s); authorizationState[from][nonce] = true; emit AuthorizationUsed(from, nonce); _transfer(from, to, value); } }
/* * SPDX-License-Identifier: GPL-3.0 */ // Copied and modified from: https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol pragma solidity ^0.6.8; import "@openzeppelin/contracts/cryptography/MerkleProof.sol"; import "@aragon/govern-contract-utils/contracts/erc20/SafeERC20.sol"; import "@aragon/govern-contract-utils/contracts/initializable/Initializable.sol"; contract MerkleDistributor is Initializable { using SafeERC20 for ERC20; ERC20 public token; bytes32 public merkleRoot; // This is a packed array of booleans. mapping (uint256 => uint256) private claimedBitMap; event Claimed(uint256 indexed index, address indexed to, uint256 amount); constructor(ERC20 _token, bytes32 _merkleRoot) public { initialize(_token, _merkleRoot); } function initialize(ERC20 _token, bytes32 _merkleRoot) public onlyInit("distributor") { token = _token; merkleRoot = _merkleRoot; } function claim(uint256 _index, address _to, uint256 _amount, bytes32[] calldata _merkleProof) external { require(!isClaimed(_index), "dist: already claimed"); require(_verifyBalanceOnTree(_index, _to, _amount, _merkleProof), "dist: proof failed"); _setClaimed(_index); token.safeTransfer(_to, _amount); emit Claimed(_index, _to, _amount); } function unclaimedBalance(uint256 _index, address _to, uint256 _amount, bytes32[] memory _proof) public view returns (uint256) { if (isClaimed(_index)) return 0; return _verifyBalanceOnTree(_index, _to, _amount, _proof) ? _amount : 0; } function _verifyBalanceOnTree(uint256 _index, address _to, uint256 _amount, bytes32[] memory _proof) internal view returns (bool) { bytes32 node = keccak256(abi.encodePacked(_index, _to, _amount)); return MerkleProof.verify(_proof, merkleRoot, node); } function isClaimed(uint256 _index) public view returns (bool) { uint256 claimedWord_index = _index / 256; uint256 claimedBit_index = _index % 256; uint256 claimedWord = claimedBitMap[claimedWord_index]; uint256 mask = (1 << claimedBit_index); return claimedWord & mask == mask; } function _setClaimed(uint256 _index) private { uint256 claimedWord_index = _index / 256; uint256 claimedBit_index = _index % 256; claimedBitMap[claimedWord_index] = claimedBitMap[claimedWord_index] | (1 << claimedBit_index); } }
/* * SPDX-License-Identifier: GPL-3.0 */ pragma solidity ^0.6.8; // A library for performing overflow-safe math, courtesy of DappHub: https://github.com/dapphub/ds-math/blob/d0ef6d6a5f/src/math.sol // Modified to include only the essentials library SafeMath { function add(uint256 x, uint256 y) internal pure returns (uint256 z) { require((z = x + y) >= x, "math: overflow"); } function sub(uint256 x, uint256 y) internal pure returns (uint256 z) { require((z = x - y) <= x, "math: underflow"); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev These functions deal with verification of Merkle trees (hash trees), */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { bytes32 proofElement = proof[i]; if (computedHash <= proofElement) { // Hash(current computed hash + current element of the proof) computedHash = keccak256(abi.encodePacked(computedHash, proofElement)); } else { // Hash(current element of the proof + current computed hash) computedHash = keccak256(abi.encodePacked(proofElement, computedHash)); } } // Check if the computed hash (root) is equal to the provided root return computedHash == root; } }
/* * SPDX-License-Identifier: GPL-3.0 */ pragma solidity 0.6.8; pragma experimental ABIEncoderV2; // required for passing structs in calldata (fairly secure at this point) import "erc3k/contracts/IERC3000.sol"; import "@aragon/govern-contract-utils/contracts/acl/ACL.sol"; import "@aragon/govern-contract-utils/contracts/adaptive-erc165/AdaptiveERC165.sol"; import "@aragon/govern-contract-utils/contracts/deposits/DepositLib.sol"; import "@aragon/govern-contract-utils/contracts/erc20/SafeERC20.sol"; import '@aragon/govern-contract-utils/contracts/safe-math/SafeMath.sol'; import "../protocol/IArbitrable.sol"; import "../protocol/IArbitrator.sol"; library GovernQueueStateLib { enum State { None, Scheduled, Challenged, Approved, Rejected, Cancelled, Executed } struct Item { State state; } function checkState(Item storage _item, State _requiredState) internal view { require(_item.state == _requiredState, "queue: bad state"); } function setState(Item storage _item, State _state) internal { _item.state = _state; } function checkAndSetState(Item storage _item, State _fromState, State _toState) internal { checkState(_item, _fromState); setState(_item, _toState); } } contract GovernQueue is IERC3000, IArbitrable, AdaptiveERC165, ACL { // Syntax sugar to enable method-calling syntax on types using ERC3000Data for *; using DepositLib for ERC3000Data.Collateral; using GovernQueueStateLib for GovernQueueStateLib.Item; using SafeERC20 for ERC20; using SafeMath for uint256; // Map '4' as the 'allow' ruling; this implicitly maps '3' as the 'reject' ruling uint256 internal constant ALLOW_RULING = 4; // Permanent state bytes32 public configHash; // keccak256 hash of the current ERC3000Data.Config uint256 public nonce; // number of scheduled payloads so far mapping (bytes32 => GovernQueueStateLib.Item) public queue; // container hash -> execution state // Temporary state mapping (bytes32 => address) public challengerCache; // container hash -> challenger addr (used after challenging and before dispute resolution) mapping (bytes32 => mapping (IArbitrator => uint256)) public disputeItemCache; // container hash -> arbitrator addr -> dispute id (used between dispute creation and ruling) /** * @param _aclRoot account that will be given root permissions on ACL (commonly given to factory) * @param _initialConfig initial configuration parameters */ constructor(address _aclRoot, ERC3000Data.Config memory _initialConfig) public ACL(_aclRoot) // note that this contract directly derives from ACL (ACL is local to contract and not global to system in Govern) { initialize(_aclRoot, _initialConfig); } function initialize(address _aclRoot, ERC3000Data.Config memory _initialConfig) public initACL(_aclRoot) onlyInit("queue") { _setConfig(_initialConfig); _registerStandard(type(IERC3000).interfaceId); } /** * @notice Schedules an action for execution, allowing for challenges and vetos on a defined time window. Pulls collateral from submitter into contract. * @param _container A ERC3000Data.Container struct holding both the payload being scheduled for execution and * the current configuration of the system */ function schedule(ERC3000Data.Container memory _container) // TO FIX: Container is in memory and function has to be public to avoid an unestrutable solidity crash public override auth(this.schedule.selector) // note that all functions in this contract are ACL protected (commonly some of them will be open for any addr to perform) returns (bytes32 containerHash) { // prevent griefing by front-running (the same container is sent by two different people and one must be challenged) // and ensure container hashes are unique require(_container.payload.nonce == ++nonce, "queue: bad nonce"); // hash using ERC3000Data.hash(ERC3000Data.Config) bytes32 _configHash = _container.config.hash(); // ensure that the hash of the config passed in the container matches the current config (implicit agreement approval by scheduler) require(_configHash == configHash, "queue: bad config"); // ensure that the time delta to the execution timestamp provided in the payload is at least after the config's execution delay require(_container.payload.executionTime >= _container.config.executionDelay.add(block.timestamp), "queue: bad delay"); // ensure that the submitter of the payload is also the sender of this call require(_container.payload.submitter == msg.sender, "queue: bad submitter"); // Restrict the size of calldata to _container.config.maxCalldataSize to make sure challenge function stays callable uint calldataSize; assembly { calldataSize := calldatasize() } require(calldataSize <= _container.config.maxCalldataSize, "calldatasize: limit exceeded"); // store and set container's hash containerHash = ERC3000Data.containerHash(_container.payload.hash(), _configHash); queue[containerHash].checkAndSetState( GovernQueueStateLib.State.None, // ensure that the state for this container is None GovernQueueStateLib.State.Scheduled // and if so perform a state transition to Scheduled ); // we don't need to save any more state about the container in storage // we just authenticate the hash and assign it a state, since all future // actions regarding the container will need to provide it as a witness // all witnesses are logged from this contract at least once, so the // trust assumption should be the same as storing all on-chain (move complexity to clients) ERC3000Data.Collateral memory collateral = _container.config.scheduleDeposit; collateral.collectFrom(_container.payload.submitter); // pull collateral from submitter (requires previous approval) // the configured resolver may specify additional out-of-band payments for scheduling actions // schedule() leaves these requirements up to the callers of `schedule()` or other users to fulfill // emit an event to ensure data availability of all state that cannot be otherwise fetched (see how config isn't emitted since an observer should already have it) emit Scheduled(containerHash, _container.payload); } /** * @notice Executes an action after its execution delay has passed and its state hasn't been altered by a challenge or veto * @param _container A ERC3000Data.Container struct holding both the payload being scheduled for execution and * the current configuration of the system */ function execute(ERC3000Data.Container memory _container) public override auth(this.execute.selector) // in most instances this will be open for any addr, but leaving configurable for flexibility returns (bytes32 failureMap, bytes[] memory) { // ensure enough time has passed require(block.timestamp >= _container.payload.executionTime, "queue: wait more"); bytes32 containerHash = _container.hash(); queue[containerHash].checkAndSetState( GovernQueueStateLib.State.Scheduled, // note that we will revert here if the container wasn't previously scheduled GovernQueueStateLib.State.Executed ); _container.config.scheduleDeposit.releaseTo(_container.payload.submitter); // release collateral to original submitter return _execute(_container.payload, containerHash); } /** * @notice Challenge a container in case its scheduling is illegal as per Config.rules. Pulls collateral and dispute fees from sender into contract * @param _container A ERC3000Data.Container struct holding both the payload being scheduled for execution and * the current configuration of the system * @param _reason Hint for case reviewers as to why the scheduled container is illegal */ function challenge(ERC3000Data.Container memory _container, bytes memory _reason) auth(this.challenge.selector) override public returns (uint256 disputeId) { bytes32 containerHash = _container.hash(); challengerCache[containerHash] = msg.sender; // cache challenger address while it is needed queue[containerHash].checkAndSetState( GovernQueueStateLib.State.Scheduled, GovernQueueStateLib.State.Challenged ); ERC3000Data.Collateral memory collateral = _container.config.challengeDeposit; collateral.collectFrom(msg.sender); // pull challenge collateral from sender // create dispute on arbitrator IArbitrator arbitrator = IArbitrator(_container.config.resolver); (address recipient, ERC20 feeToken, uint256 feeAmount) = arbitrator.getDisputeFees(); require(feeToken.safeTransferFrom(msg.sender, address(this), feeAmount), "queue: bad fee pull"); require(feeToken.safeApprove(recipient, feeAmount), "queue: bad approve"); disputeId = arbitrator.createDispute(2, abi.encode(_container)); // create dispute sending full container ABI encoded (could prob just send payload to save gas) require(feeToken.safeApprove(recipient, 0), "queue: bad reset"); // reset just in case non-compliant tokens (that fail on non-zero to non-zero approvals) are used // submit both arguments as evidence and close evidence period. no more evidence can be submitted and a settlement can't happen (could happen off-protocol) arbitrator.submitEvidence(disputeId, _container.payload.submitter, _container.payload.proof); arbitrator.submitEvidence(disputeId, msg.sender, _reason); arbitrator.closeEvidencePeriod(disputeId); disputeItemCache[containerHash][arbitrator] = disputeId + 1; // cache a relation between disputeId and containerHash while needed emit Challenged(containerHash, msg.sender, _reason, disputeId, collateral); } /** * @notice Apply arbitrator's ruling over a challenge once it has come to a final ruling * @param _container A ERC3000Data.Container struct holding both the payload being scheduled for execution and * the current configuration of the system * @param _disputeId disputeId in the arbitrator in which the dispute over the container was created */ function resolve(ERC3000Data.Container memory _container, uint256 _disputeId) override public returns (bytes32 failureMap, bytes[] memory) { bytes32 containerHash = _container.hash(); IArbitrator arbitrator = IArbitrator(_container.config.resolver); require(disputeItemCache[containerHash][arbitrator] == _disputeId + 1, "queue: bad dispute id"); delete disputeItemCache[containerHash][arbitrator]; // release state to refund gas; no longer needed in state queue[containerHash].checkState(GovernQueueStateLib.State.Challenged); (address subject, uint256 ruling) = arbitrator.rule(_disputeId); require(subject == address(this), "queue: not subject"); bool arbitratorApproved = ruling == ALLOW_RULING; queue[containerHash].setState( arbitratorApproved ? GovernQueueStateLib.State.Approved : GovernQueueStateLib.State.Rejected ); emit Resolved(containerHash, msg.sender, arbitratorApproved); emit Ruled(arbitrator, _disputeId, ruling); if (arbitratorApproved) { return _executeApproved(_container); } else { return _settleRejection(_container); } } function veto(ERC3000Data.Container memory _container, bytes memory _reason) auth(this.veto.selector) override public { bytes32 containerHash = _container.hash(); GovernQueueStateLib.Item storage item = queue[containerHash]; if (item.state == GovernQueueStateLib.State.Challenged) { item.checkAndSetState( GovernQueueStateLib.State.Challenged, GovernQueueStateLib.State.Cancelled ); address challenger = challengerCache[containerHash]; // release state to refund gas; no longer needed in state delete challengerCache[containerHash]; delete disputeItemCache[containerHash][IArbitrator(_container.config.resolver)]; // release collateral to challenger and scheduler _container.config.scheduleDeposit.releaseTo(_container.payload.submitter); _container.config.challengeDeposit.releaseTo(challenger); } else { // If the given container doesn't have the state Challenged // has it to be the Scheduled state and otherwise should it throw as expected item.checkAndSetState( GovernQueueStateLib.State.Scheduled, GovernQueueStateLib.State.Cancelled ); _container.config.scheduleDeposit.releaseTo(_container.payload.submitter); } emit Vetoed(containerHash, msg.sender, _reason); } /** * @notice Apply a new configuration for all *new* containers to be scheduled * @param _config A ERC3000Data.Config struct holding all the new params that will control the queue */ function configure(ERC3000Data.Config memory _config) public override auth(this.configure.selector) returns (bytes32) { return _setConfig(_config); } // Internal function _executeApproved(ERC3000Data.Container memory _container) internal returns (bytes32 failureMap, bytes[] memory) { bytes32 containerHash = _container.hash(); queue[containerHash].checkAndSetState( GovernQueueStateLib.State.Approved, GovernQueueStateLib.State.Executed ); delete challengerCache[containerHash]; // release state to refund gas; no longer needed in state // release all collateral to submitter _container.config.scheduleDeposit.releaseTo(_container.payload.submitter); _container.config.challengeDeposit.releaseTo(_container.payload.submitter); return _execute(_container.payload, containerHash); } function _settleRejection(ERC3000Data.Container memory _container) internal returns (bytes32, bytes[] memory) { bytes32 containerHash = _container.hash(); queue[containerHash].checkAndSetState( GovernQueueStateLib.State.Rejected, GovernQueueStateLib.State.Cancelled ); address challenger = challengerCache[containerHash]; delete challengerCache[containerHash]; // release state to refund gas; no longer needed in state // release all collateral to challenger _container.config.scheduleDeposit.releaseTo(challenger); _container.config.challengeDeposit.releaseTo(challenger); // return zero values as nothing is executed on rejection } function _execute(ERC3000Data.Payload memory _payload, bytes32 _containerHash) internal returns (bytes32, bytes[] memory) { emit Executed(_containerHash, msg.sender); return _payload.executor.exec(_payload.actions, _payload.allowFailuresMap, _containerHash); } function _setConfig(ERC3000Data.Config memory _config) internal returns (bytes32) { // validate collaterals by calling balanceOf on their interface if(_config.challengeDeposit.amount != 0 && _config.challengeDeposit.token != address(0)) { (bool ok, bytes memory value) = _config.challengeDeposit.token.call( abi.encodeWithSelector(ERC20.balanceOf.selector, address(this)) ); require(ok && value.length > 0, "queue: bad config"); } if(_config.scheduleDeposit.amount != 0 && _config.scheduleDeposit.token != address(0)) { (bool ok, bytes memory value) = _config.scheduleDeposit.token.call( abi.encodeWithSelector(ERC20.balanceOf.selector, address(this)) ); require(ok && value.length > 0, "queue: bad config"); } configHash = _config.hash(); emit Configured(configHash, msg.sender, _config); return configHash; } }
/* * SPDX-License-Identifier: MIT */ pragma solidity ^0.6.8; import "erc3k/contracts/ERC3000Data.sol"; import "../erc20/ERC20.sol"; import "../erc20/SafeERC20.sol"; library DepositLib { using SafeERC20 for ERC20; event Locked(address indexed token, address indexed from, uint256 amount); event Unlocked(address indexed token, address indexed to, uint256 amount); function collectFrom(ERC3000Data.Collateral memory _collateral, address _from) internal { if (_collateral.amount > 0) { ERC20 token = ERC20(_collateral.token); require(token.safeTransferFrom(_from, address(this), _collateral.amount), "deposit: bad token lock"); emit Locked(_collateral.token, _from, _collateral.amount); } } function releaseTo(ERC3000Data.Collateral memory _collateral, address _to) internal { if (_collateral.amount > 0) { ERC20 token = ERC20(_collateral.token); require(token.safeTransfer(_to, _collateral.amount), "deposit: bad token release"); emit Unlocked(_collateral.token, _to, _collateral.amount); } } }
/* * SPDX-License-Identifier: MIT */ // From https://github.com/aragon/protocol/blob/f1b3361a160da92b9bb449c0a05dee0c30e41594/packages/evm/contracts/arbitration/IArbitrable.sol pragma solidity ^0.6.8; import "./IArbitrator.sol"; /** * @dev The Arbitrable instances actually don't require to follow any specific interface. * Note that this is actually optional, although it does allow the Protocol to at least have a way to identify a specific set of instances. */ abstract contract IArbitrable { /** * @dev Emitted when an IArbitrable instance's dispute is ruled by an IArbitrator * @param arbitrator IArbitrator instance ruling the dispute * @param disputeId Identification number of the dispute being ruled by the arbitrator * @param ruling Ruling given by the arbitrator */ event Ruled(IArbitrator indexed arbitrator, uint256 indexed disputeId, uint256 ruling); }
/* * SPDX-License-Identifier: MIT */ // From https://github.com/aragon/protocol/blob/f1b3361a160da92b9bb449c0a05dee0c30e41594/packages/evm/contracts/arbitration/IArbitrator.sol pragma solidity ^0.6.8; import "@aragon/govern-contract-utils/contracts/erc20/ERC20.sol"; interface IArbitrator { /** * @dev Create a dispute over the Arbitrable sender with a number of possible rulings * @param _possibleRulings Number of possible rulings allowed for the dispute * @param _metadata Optional metadata that can be used to provide additional information on the dispute to be created * @return Dispute identification number */ function createDispute(uint256 _possibleRulings, bytes calldata _metadata) external returns (uint256); /** * @dev Submit evidence for a dispute * @param _disputeId Id of the dispute in the Protocol * @param _submitter Address of the account submitting the evidence * @param _evidence Data submitted for the evidence related to the dispute */ function submitEvidence(uint256 _disputeId, address _submitter, bytes calldata _evidence) external; /** * @dev Close the evidence period of a dispute * @param _disputeId Identification number of the dispute to close its evidence submitting period */ function closeEvidencePeriod(uint256 _disputeId) external; /** * @notice Rule dispute #`_disputeId` if ready * @param _disputeId Identification number of the dispute to be ruled * @return subject Subject associated to the dispute * @return ruling Ruling number computed for the given dispute */ function rule(uint256 _disputeId) external returns (address subject, uint256 ruling); /** * @dev Tell the dispute fees information to create a dispute * @return recipient Address where the corresponding dispute fees must be transferred to * @return feeToken ERC20 token used for the fees * @return feeAmount Total amount of fees that must be allowed to the recipient */ function getDisputeFees() external view returns (address recipient, ERC20 feeToken, uint256 feeAmount); /** * @dev Tell the payments recipient address * @return Address of the payments recipient module */ function getPaymentsRecipient() external view returns (address); }
/* * SPDX-License-Identifier: GPL-3.0 */ pragma solidity 0.6.8; pragma experimental ABIEncoderV2; import "@aragon/govern-token/contracts/GovernMinter.sol"; import "@aragon/govern-token/contracts/GovernToken.sol"; import "@aragon/govern-token/contracts/libraries/TokenLib.sol"; contract GovernTokenFactoryMock { event NewTokenCalledWith(address initialMinter, string _tokenName, string _tokenSymbol, uint8 tokenDecimals, address mintAddr, uint256 mintAmount, bool useProxies); function newToken( address _initialMinter, TokenLib.TokenConfig calldata _token, bool _useProxies ) external returns ( GovernToken token, GovernMinter minter ) { emit NewTokenCalledWith( _initialMinter, _token.tokenName, _token.tokenSymbol, _token.tokenDecimals, _token.mintAddress, _token.mintAmount, _useProxies ); token = GovernToken(address(this)); minter = GovernMinter(address(this)); } }
/* * SPDX-License-Identifier: GPL-3.0 */ pragma solidity 0.6.8; pragma experimental ABIEncoderV2; import "@aragon/govern-core/contracts/pipelines/GovernQueue.sol"; import "@aragon/govern-contract-utils/contracts/acl/ACL.sol"; contract GovernQueueFactoryMock { event NewQueueCalledWith(address aclRoot, bytes32 salt); event BulkCalled(ACLData.BulkItem[] items); bytes4 public constant ROOT_ROLE = "0x"; function schedule() public pure {} function execute() public pure {} function challenge() public pure {} function configure(ERC3000Data.Config memory /*_config*/) public pure returns(bool) { // TODO: emit events and catch it in the govern-base-factory-unit.test.ts return true; } // probably ACL inheritance can be used instead of implementing ACL functions again. function grant(bytes4 _role, address _who) public pure { // TODO: emit events and catch it in the govern-base-factory-unit.test.ts } function revoke(bytes4 _role, address _who) public pure { // TODO: emit events and catch it in the govern-base-factory-unit.test.ts } function bulk(ACLData.BulkItem[] memory items) public { emit BulkCalled(items); } function newQueue(address _aclRoot, ERC3000Data.Config memory /*_config*/, bytes32 _salt) public returns (GovernQueue queue) { /* TODO:There seems to be a bug with waffle. After it's been fixed, emit the _config too and in the test, assert it. https://github.com/EthWorks/Waffle/issues/454 */ emit NewQueueCalledWith(_aclRoot, _salt); return GovernQueue(address(this)); } }
/* * SPDX-License-Identifier: GPL-3.0 */ pragma solidity 0.6.8; import "erc3k/contracts/IERC3000.sol"; import "@aragon/govern-core/contracts/Govern.sol"; import "@aragon/govern-contract-utils/contracts/address-utils/AddressUtils.sol"; contract GovernFactoryMock { using AddressUtils for address; event NewGovernCalledWith(IERC3000 executor, bytes32 salt); function newGovern(IERC3000 _initialExecutor, bytes32 _salt) public returns (Govern govern) { emit NewGovernCalledWith(_initialExecutor, _salt); return Govern(address(this).toPayable()); } }
{ "optimizer": { "enabled": true, "runs": 20000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "metadata": { "useLiteralContent": true } }
[{"inputs":[{"internalType":"contract GovernRegistry","name":"_registry","type":"address"},{"internalType":"contract GovernFactory","name":"_governFactory","type":"address"},{"internalType":"contract GovernQueueFactory","name":"_queueFactory","type":"address"},{"internalType":"contract GovernTokenFactory","name":"_tokenFactory","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"governFactory","outputs":[{"internalType":"contract GovernFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"tokenAddress","type":"address"},{"internalType":"uint8","name":"tokenDecimals","type":"uint8"},{"internalType":"string","name":"tokenName","type":"string"},{"internalType":"string","name":"tokenSymbol","type":"string"},{"internalType":"address","name":"mintAddress","type":"address"},{"internalType":"uint256","name":"mintAmount","type":"uint256"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"merkleMintAmount","type":"uint256"},{"internalType":"bytes","name":"merkleTree","type":"bytes"},{"internalType":"bytes","name":"merkleContext","type":"bytes"}],"internalType":"struct TokenLib.TokenConfig","name":"_token","type":"tuple"},{"internalType":"address[]","name":"_scheduleAccessList","type":"address[]"},{"internalType":"bool","name":"_useProxies","type":"bool"},{"components":[{"internalType":"uint256","name":"executionDelay","type":"uint256"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ERC3000Data.Collateral","name":"scheduleDeposit","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ERC3000Data.Collateral","name":"challengeDeposit","type":"tuple"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"bytes","name":"rules","type":"bytes"},{"internalType":"uint256","name":"maxCalldataSize","type":"uint256"}],"internalType":"struct ERC3000Data.Config","name":"_config","type":"tuple"},{"internalType":"string","name":"_name","type":"string"}],"name":"newGovern","outputs":[{"internalType":"contract Govern","name":"govern","type":"address"},{"internalType":"contract GovernQueue","name":"queue","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"queueFactory","outputs":[{"internalType":"contract GovernQueueFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract GovernRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenFactory","outputs":[{"internalType":"contract GovernTokenFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b50604051620019a6380380620019a6833981016040819052620000349162000089565b600080546001600160a01b03199081166001600160a01b039586161790915560018054821693851693909317909255600280548316918416919091179055600380549091169290911691909117905562000109565b600080600080608085870312156200009f578384fd5b8451620000ac81620000f0565b6020860151909450620000bf81620000f0565b6040860151909350620000d281620000f0565b6060860151909250620000e581620000f0565b939692955090935050565b6001600160a01b03811681146200010657600080fd5b50565b61188d80620001196000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80637b103999116100505780637b103999146100ab57806389409516146100b3578063e77772fe146100bb57610067565b80635f3485551461006c5780636ca4110e14610096575b600080fd5b61007f61007a3660046110c4565b6100c3565b60405161008d929190611499565b60405180910390f35b61009e610e31565b60405161008d9190611452565b61009e610e4d565b61009e610e69565b61009e610e85565b600080600a8888905011156040518060600160405280602381526020016118356023913990610128576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161011f9190611692565b60405180910390fd5b50600086610137576000610161565b848460405160200161014a9291906112bc565b604051602081830303815290604052805190602001205b6001546040517fa691fc6700000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff169063a691fc67906101bc9030908a9086906004016112cc565b602060405180830381600087803b1580156101d657600080fd5b505af11580156101ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061020e919061106f565b6000546040517fad921bf400000000000000000000000000000000000000000000000000000000815291935073ffffffffffffffffffffffffffffffffffffffff169063ad921bf4906102679085908590600401611473565b602060405180830381600087803b15801561028157600080fd5b505af1158015610295573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b9919061106f565b925060006102ca60208c018c610ff4565b9050600073ffffffffffffffffffffffffffffffffffffffff82166107b157600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ee3286fe868e8c6040518463ffffffff1660e01b815260040161034893929190611525565b6040805180830381600087803b15801561036157600080fd5b505af1158015610375573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610399919061108b565b909250905060006103b060408a0160208b01610ff4565b73ffffffffffffffffffffffffffffffffffffffff1614806103f7575060006103df60808a0160608b01610ff4565b73ffffffffffffffffffffffffffffffffffffffff16145b156107b1576040517fa157a10d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063a157a10d90610470907f7744efda0000000000000000000000000000000000000000000000000000000090309060040161140a565b600060405180830381600087803b15801561048a57600080fd5b505af115801561049e573d6000803e3d6000fd5b505050506104aa610ea1565b6040518060c001604052808a6000013581526020016040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168d60200160000160208101906104f89190610ff4565b73ffffffffffffffffffffffffffffffffffffffff16141561051a578661052a565b61052a60408e0160208f01610ff4565b73ffffffffffffffffffffffffffffffffffffffff1681526020018c6020016020013581525081526020016040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff168d606001600001602081019061058e9190610ff4565b73ffffffffffffffffffffffffffffffffffffffff1614156105b057866105c0565b6105c060808e0160608f01610ff4565b73ffffffffffffffffffffffffffffffffffffffff16815260808d0135602091820152908252016105f760c08c0160a08d01610ff4565b73ffffffffffffffffffffffffffffffffffffffff16815260200161061f60c08c018c611728565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060e08b01356020909101526040517f7744efda00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff861690637744efda906106b69084906004016116a5565b602060405180830381600087803b1580156106d057600080fd5b505af11580156106e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107089190611017565b506040517f5884973400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86169063588497349061077d907f7744efda0000000000000000000000000000000000000000000000000000000090309060040161140a565b600060405180830381600087803b15801561079757600080fd5b505af11580156107ab573d6000803e3d6000fd5b50505050505b6003546040517f776ff4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063776ff4bd906108119088908890879087908e908e906004016114c0565b600060405180830381600087803b15801561082b57600080fd5b505af115801561083f573d6000803e3d6000fd5b5060009250508b1590506108565760068b01610859565b60075b905060608167ffffffffffffffff8111801561087457600080fd5b506040519080825280602002602001820160405280156108ae57816020015b61089b610ef9565b8152602001906001900390816108935790505b50604080516060810190915290915080600081527f3da956aa00000000000000000000000000000000000000000000000000000000602082015273ffffffffffffffffffffffffffffffffffffffff6040909101528151829060009061091057fe5b6020908102919091010152604080516060810190915280600081527f1f13405b00000000000000000000000000000000000000000000000000000000602082015273ffffffffffffffffffffffffffffffffffffffff60409091015281518290600190811061097b57fe5b6020908102919091010152604080516060810190915280600081527f7744efda00000000000000000000000000000000000000000000000000000000602082015273ffffffffffffffffffffffffffffffffffffffff89166040909101528151829060029081106109e857fe5b6020908102919091010152604080516060810190915280600181526020018773ffffffffffffffffffffffffffffffffffffffff16637e8c7f086040518163ffffffff1660e01b815260040160206040518083038186803b158015610a4c57600080fd5b505afa158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a84919061102f565b7fffffffff0000000000000000000000000000000000000000000000000000000016815230602090910152815182906003908110610abe57fe5b6020908102919091010152604080516060810190915280600081526020018773ffffffffffffffffffffffffffffffffffffffff16637e8c7f086040518163ffffffff1660e01b815260040160206040518083038186803b158015610b2257600080fd5b505afa158015610b36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b5a919061102f565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020018873ffffffffffffffffffffffffffffffffffffffff1681525081600481518110610ba557fe5b6020908102919091010152604080516060810190915280600281526020018773ffffffffffffffffffffffffffffffffffffffff16637e8c7f086040518163ffffffff1660e01b815260040160206040518083038186803b158015610c0957600080fd5b505afa158015610c1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c41919061102f565b7fffffffff000000000000000000000000000000000000000000000000000000001681526000602090910152815182906005908110610c7c57fe5b60209081029190910101528b610cfc57604080516060810190915280600081527fc832048000000000000000000000000000000000000000000000000000000000602082015273ffffffffffffffffffffffffffffffffffffffff604090910152815182906006908110610cec57fe5b6020026020010181905250610d9c565b60005b8c811015610d9a5760408051606081018252600081527fc83204800000000000000000000000000000000000000000000000000000000060208201529081018f8f84818110610d4a57fe5b9050602002016020810190610d5f9190610ff4565b73ffffffffffffffffffffffffffffffffffffffff16815250828260060181518110610d8757fe5b6020908102919091010152600101610cff565b505b6040517f1c47671b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff871690631c47671b90610dee90849060040161136f565b600060405180830381600087803b158015610e0857600080fd5b505af1158015610e1c573d6000803e3d6000fd5b50505050505050505097509795505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60035473ffffffffffffffffffffffffffffffffffffffff1681565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b6040518060c0016040528060008152602001610ebb610f1b565b8152602001610ec8610f1b565b8152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160608152602001600081525090565b6040805160608101909152806000815260006020820181905260409091015290565b604080518082019091526000808252602082015290565b60008083601f840112610f43578182fd5b50813567ffffffffffffffff811115610f5a578182fd5b6020830191508360208083028501011115610f7457600080fd5b9250929050565b80358015158114610f8b57600080fd5b92915050565b8035610f8b8161180f565b60008083601f840112610fad578182fd5b50813567ffffffffffffffff811115610fc4578182fd5b602083019150836020828501011115610f7457600080fd5b60006101008284031215610fee578081fd5b50919050565b600060208284031215611005578081fd5b81356110108161180f565b9392505050565b600060208284031215611028578081fd5b5051919050565b600060208284031215611040578081fd5b81517fffffffff0000000000000000000000000000000000000000000000000000000081168114611010578182fd5b600060208284031215611080578081fd5b81516110108161180f565b6000806040838503121561109d578081fd5b82516110a88161180f565b60208401519092506110b98161180f565b809150509250929050565b600080600080600080600060a0888a0312156110de578283fd5b873567ffffffffffffffff808211156110f5578485fd5b818a01610140818d031215611108578586fd5b985060208a013591508082111561111d578485fd5b6111298b838c01610f32565b909850965061113b8b60408c01610f7b565b955060608a0135915080821115611150578485fd5b61115c8b838c01610fdc565b945060808a0135915080821115611171578384fd5b5061117e8a828b01610f9c565b989b979a50959850939692959293505050565b73ffffffffffffffffffffffffffffffffffffffff169052565b15159052565b600082845282826020860137806020848601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011685010190509392505050565b60008151808452815b8181101561121e57602081850181015186830182015201611202565b8181111561122f5782602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b803561126d8161180f565b73ffffffffffffffffffffffffffffffffffffffff168252602090810135910152565b805173ffffffffffffffffffffffffffffffffffffffff168252602090810151910152565b60ff169052565b6000828483379101908152919050565b600073ffffffffffffffffffffffffffffffffffffffff808616835260606020840152843560608401526113066080840160208701611262565b61131660c0840160608701611262565b60a08501356113248161180f565b6101008282168186015261133b60c088018861179a565b935091508061012086015250611356610160850183836111b1565b60e0969096013561014085015250505060400152919050565b602080825282518282018190526000919060409081850190868401855b828110156113fd5781518051600381106113a257fe5b8552808701517fffffffff00000000000000000000000000000000000000000000000000000000168786015285015173ffffffffffffffffffffffffffffffffffffffff16858501526060909301929085019060010161138c565b5091979650505050505050565b7fffffffff0000000000000000000000000000000000000000000000000000000092909216825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525060c0608083015261150a60c0830184866111b1565b82810360a09093019290925281526020019695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff8516825260606020830152602084016115616060840161155c8388610f91565b611191565b61156b81866117fd565b61157860808501826112b5565b5050611587604085018561179a565b6101408060a086015261159f6101a0860183856111b1565b6115ac606089018961179a565b945092507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0808783030160c08801526115e68286866111b1565b6115f360808b018b61178d565b955061160260e0890187611191565b610100955060a08a013586890152610120945060c08a01358589015260e08a013584890152611633868b018b61179a565b94509250818882030161016089015261164d8185856111b1565b95505061165c848a018a61179a565b935091508087860301610180880152506116778483836111b1565b94505050505061168a60408301846111ab565b949350505050565b60006020825261101060208301846111f9565b6000602082528251602083015260208301516116c46040840182611290565b5060408301516116d76080840182611290565b5073ffffffffffffffffffffffffffffffffffffffff60608401511660c083015260808301516101008060e08501526117146101208501836111f9565b60a095909501519301929092525090919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261175c578283fd5b8084018035925067ffffffffffffffff831115611777578384fd5b60200192505036819003821315610f7457600080fd5b600082356110108161180f565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126117ce578283fd5b830160208101925035905067ffffffffffffffff8111156117ee57600080fd5b803603831315610f7457600080fd5b6000823560ff81168114611010578182fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461183157600080fd5b5056fe62617365666163746f72793a207363686564756c65206c697374206578636565646564a26469706673582212205ba2a73ae95cc85967582fd12e139382da6d9a9584441a33bc67112868eddbfb64736f6c63430006080033000000000000000000000000cc3f32957d316a12afcfed04c0716af4814ecb2b0000000000000000000000003ddc3e8bbf3f6987e4008a7d6f486dae4d0f120f0000000000000000000000007e9f0fa00545ac62f224e23aae0ff0e7bc5b0dc3000000000000000000000000d4b22050b8ea9fdd28bbc59e6f2a6aea64dbd1a6
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.