- Contract name:
- InitialAirdrop
- Optimization enabled
- true
- Compiler version
- v0.7.6+commit.7338295f
- Optimization runs
- 200
- Verified at
- 2022-07-13T21:03:57.105333Z
./contracts/genesis/implementation/InitialAirdrop.sol
// SPDX-License-Identifier: MIT pragma solidity 0.7.6; import "../../governance/implementation/GovernedAtGenesis.sol"; import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts/math/Math.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import "../../utils/implementation/SafePct.sol"; /** * @title InitialAirdrop * @notice A contract to manage the initial airdrop allocation. * @notice The balance that will be added to this contract must initially be a part of circulating supply **/ contract InitialAirdrop is GovernedAtGenesis, ReentrancyGuard { using SafeMath for uint256; using SafePct for uint256; // constants uint256 internal constant CLAIMED_AT_GENESIS_BIPS = 1500; uint256 internal constant TOTAL_BIPS = 10000; // storage address[] public airdropAccounts; mapping(address => uint256) public airdropAmountsWei; uint256 public totalInitialAirdropWei; // Total wei to be distributed by this contract (initial airdrop) uint256 public initialAirdropStartTs; // Day 0 when airdrop starts uint256 public latestAirdropStartTs; // Latest day 0 when airdrop starts uint256 public totalTransferredAirdropWei; // All wei already transferred uint256 public nextAirdropAccountIndexToTransfer; // Errors string internal constant ERR_OUT_OF_BALANCE = "balance too low"; string internal constant ERR_TOO_MANY = "too many"; string internal constant ERR_NOT_STARTED = "not started"; string internal constant ERR_ARRAY_MISMATCH = "arrays lengths mismatch"; string internal constant ERR_ALREADY_SET = "already set"; string internal constant ERR_WRONG_START_TIMESTAMP = "wrong start timestamp"; string internal constant ERR_ALREADY_STARTED = "already started"; // Events event AccountsAdded(address[] accounts); event AirdropStart(uint256 initialAirdropStartTs); event AirdropTransferFailure(address indexed account, uint256 amountWei); /** * @dev This modifier ensures that this contract's balance matches the expected balance. */ modifier mustBalance { _; require (_getExpectedBalance() <= address(this).balance, ERR_OUT_OF_BALANCE); } /** * @dev This modifier ensures that the airdrop was already started */ modifier airdropStarted { require (initialAirdropStartTs != 0 && initialAirdropStartTs < block.timestamp, ERR_NOT_STARTED); _; } /** * @dev This constructor should contain no code as this contract is pre-loaded into the genesis block. * The super constructor is called for testing convenience. */ constructor() GovernedAtGenesis(address(0)) { /* empty block */ } /** * @notice Method to set addresses and their respective balances in batches to this contract (initial airdrop) * @param _accounts Array of adresses we are adding in batch * @param _balances Array of balances to be airdropped to respective accounts (total amount - 100%) * @dev Note that _toAddresses and _balances arrays must be of equal length * @dev Note that script must use the same batches to fill data (if restarted), otherwise duplicates may occure */ function setAirdropBalances(address[] calldata _accounts, uint256[] calldata _balances) external onlyGovernance { require(_accounts.length <= 1000, ERR_TOO_MANY); require(_accounts.length == _balances.length, ERR_ARRAY_MISMATCH); require (initialAirdropStartTs == 0, ERR_ALREADY_STARTED); if (airdropAmountsWei[_accounts[0]] > 0) return; // batch already added for (uint16 i = 0; i < _accounts.length; i++) { address airdropAccount = _accounts[i]; uint256 airdropAmountWei = _balances[i].mulDiv(CLAIMED_AT_GENESIS_BIPS, TOTAL_BIPS); airdropAccounts.push(airdropAccount); airdropAmountsWei[airdropAccount] = airdropAmountWei; totalInitialAirdropWei = totalInitialAirdropWei.add(airdropAmountWei); } // We added the accounts to airdrop, emit event emit AccountsAdded(_accounts); } /** * @notice Latest start of the initial airdrop at _latestAirdropStartTs timestamp * @param _latestAirdropStartTs point in time when latest start is possible */ function setLatestAirdropStart(uint256 _latestAirdropStartTs) external onlyGovernance { require(latestAirdropStartTs == 0, ERR_ALREADY_SET); latestAirdropStartTs = _latestAirdropStartTs; } /** * @notice Start the initial airdrop at _initialAirdropStartTs timestamp * @param _initialAirdropStartTs point in time when we start * @dev should be called immediately after all airdrop accounts and balances are set */ function setAirdropStart(uint256 _initialAirdropStartTs) external onlyGovernance mustBalance { require(initialAirdropStartTs == 0 || initialAirdropStartTs > block.timestamp, ERR_ALREADY_STARTED); require(initialAirdropStartTs < _initialAirdropStartTs && _initialAirdropStartTs <= latestAirdropStartTs, ERR_WRONG_START_TIMESTAMP); initialAirdropStartTs = _initialAirdropStartTs; emit AirdropStart(_initialAirdropStartTs); } /** * @notice Method for transfering initial airdrop amounts in batches of 50 */ function transferAirdrop() external airdropStarted mustBalance nonReentrant { uint256 upperBound = Math.min(nextAirdropAccountIndexToTransfer + 50, airdropAccounts.length); for (uint256 i = nextAirdropAccountIndexToTransfer; i < upperBound; i++) { // Get the account and amount address account = airdropAccounts[i]; uint256 amountWei = airdropAmountsWei[account]; // update state delete airdropAmountsWei[account]; delete airdropAccounts[i]; // Update grand total transferred totalTransferredAirdropWei = totalTransferredAirdropWei.add(amountWei); // Send /* solhint-disable avoid-low-level-calls */ //slither-disable-next-line arbitrary-send (bool success, ) = account.call{ value: amountWei, gas: 21000 }(""); /* solhint-enable avoid-low-level-calls */ if (!success) { emit AirdropTransferFailure(account, amountWei); } } // Update current position nextAirdropAccountIndexToTransfer = upperBound; } /** * @notice Return the number of airdrop accounts */ function airdropAccountsLength() external view returns (uint256) { return airdropAccounts.length; } /** * @notice Compute the expected balance of this contract. * @param _balanceExpectedWei The computed balance expected. */ function _getExpectedBalance() private view returns(uint256 _balanceExpectedWei) { return totalInitialAirdropWei.sub(totalTransferredAirdropWei); } }
@openzeppelin/contracts/math/Math.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } }
./contracts/governance/implementation/GovernedAtGenesis.sol
// SPDX-License-Identifier: MIT pragma solidity 0.7.6; import "./GovernedBase.sol"; /** * @title Governed At Genesis * @dev This contract enforces a fixed governance address when the constructor * is not executed on a contract (for instance when directly loaded to the genesis block). * This is required to fix governance on a contract when the network starts, at such point * where theoretically no accounts yet exist, and leaving it ungoverned could result in a race * to claim governance by an unauthorized address. **/ contract GovernedAtGenesis is GovernedBase { constructor(address _governance) GovernedBase(_governance) { } /** * @notice Set governance to a fixed address when constructor is not called. **/ function initialiseFixedAddress() public virtual returns (address) { address governanceAddress = address(0xfffEc6C83c8BF5c3F4AE0cCF8c45CE20E4560BD7); super.initialise(governanceAddress); return governanceAddress; } /** * @notice Disallow initialise to be called * @param _governance The governance address for initial claiming **/ // solhint-disable-next-line no-unused-vars function initialise(address _governance) public override pure { assert(false); } }
./contracts/governance/implementation/GovernedBase.sol
// SPDX-License-Identifier: MIT pragma solidity 0.7.6; import "../../userInterfaces/IGovernanceSettings.sol"; /** * @title Governed Base * @notice This abstract base class defines behaviors for a governed contract. * @dev This class is abstract so that specific behaviors can be defined for the constructor. * Contracts should not be left ungoverned, but not all contract will have a constructor * (for example those pre-defined in genesis). **/ abstract contract GovernedBase { struct TimelockedCall { uint256 allowedAfterTimestamp; bytes encodedCall; } // solhint-disable-next-line const-name-snakecase IGovernanceSettings public constant governanceSettings = IGovernanceSettings(0x1000000000000000000000000000000000000007); address private initialGovernance; bool private initialised; bool public productionMode; bool private executing; mapping(bytes4 => TimelockedCall) public timelockedCalls; event GovernanceCallTimelocked(bytes4 selector, uint256 allowedAfterTimestamp, bytes encodedCall); event TimelockedGovernanceCallExecuted(bytes4 selector, uint256 timestamp); event TimelockedGovernanceCallCanceled(bytes4 selector, uint256 timestamp); event GovernanceInitialised(address initialGovernance); event GovernedProductionModeEntered(address governanceSettings); modifier onlyGovernance { if (executing || !productionMode) { _beforeExecute(); _; } else { _recordTimelockedCall(msg.data); } } modifier onlyImmediateGovernance () { _checkOnlyGovernance(); _; } constructor(address _initialGovernance) { if (_initialGovernance != address(0)) { initialise(_initialGovernance); } } /** * @notice Execute the timelocked governance calls once the timelock period expires. * @dev Only executor can call this method. * @param _selector The method selector (only one timelocked call per method is stored). */ function executeGovernanceCall(bytes4 _selector) external { require(governanceSettings.isExecutor(msg.sender), "only executor"); TimelockedCall storage call = timelockedCalls[_selector]; require(call.allowedAfterTimestamp != 0, "timelock: invalid selector"); require(block.timestamp >= call.allowedAfterTimestamp, "timelock: not allowed yet"); bytes memory encodedCall = call.encodedCall; delete timelockedCalls[_selector]; executing = true; //solhint-disable-next-line avoid-low-level-calls (bool success,) = address(this).call(encodedCall); executing = false; emit TimelockedGovernanceCallExecuted(_selector, block.timestamp); _passReturnOrRevert(success); } /** * Cancel a timelocked governance call before it has been executed. * @dev Only governance can call this method. * @param _selector The method selector. */ function cancelGovernanceCall(bytes4 _selector) external onlyImmediateGovernance { require(timelockedCalls[_selector].allowedAfterTimestamp != 0, "timelock: invalid selector"); emit TimelockedGovernanceCallCanceled(_selector, block.timestamp); delete timelockedCalls[_selector]; } /** * Enter the production mode after all the initial governance settings have been set. * This enables timelocks and the governance is afterwards obtained by calling * governanceSettings.getGovernanceAddress(). */ function switchToProductionMode() external { _checkOnlyGovernance(); require(!productionMode, "already in production mode"); initialGovernance = address(0); productionMode = true; emit GovernedProductionModeEntered(address(governanceSettings)); } /** * @notice Initialize the governance address if not first initialized. */ function initialise(address _initialGovernance) public virtual { require(initialised == false, "initialised != false"); initialised = true; initialGovernance = _initialGovernance; emit GovernanceInitialised(_initialGovernance); } /** * Returns the current effective governance address. */ function governance() public view returns (address) { return productionMode ? governanceSettings.getGovernanceAddress() : initialGovernance; } function _beforeExecute() private { if (executing) { // can only be run from executeGovernanceCall(), where we check that only executor can call // make sure nothing else gets executed, even in case of reentrancy assert(msg.sender == address(this)); executing = false; } else { // must be called with: productionMode=false // must check governance in this case _checkOnlyGovernance(); } } function _recordTimelockedCall(bytes calldata _data) private { _checkOnlyGovernance(); bytes4 selector; //solhint-disable-next-line no-inline-assembly assembly { selector := calldataload(_data.offset) } uint256 timelock = governanceSettings.getTimelock(); uint256 allowedAt = block.timestamp + timelock; timelockedCalls[selector] = TimelockedCall({ allowedAfterTimestamp: allowedAt, encodedCall: _data }); emit GovernanceCallTimelocked(selector, allowedAt, _data); } function _checkOnlyGovernance() private view { require(msg.sender == governance(), "only governance"); } function _passReturnOrRevert(bool _success) private pure { // pass exact return or revert data - needs to be done in assembly //solhint-disable-next-line no-inline-assembly assembly { let size := returndatasize() let ptr := mload(0x40) mstore(0x40, add(ptr, size)) returndatacopy(ptr, 0, size) if _success { return(ptr, size) } revert(ptr, size) } } }
./contracts/userInterfaces/IGovernanceSettings.sol
// SPDX-License-Identifier: MIT pragma solidity 0.7.6; /** * A special contract that holds Flare governance address. * This contract enables updating governance address and timelock only by hard forking the network, * meaning only by updating validator code. */ interface IGovernanceSettings { /** * Get the governance account address. * The governance address can only be changed by a hardfork. */ function getGovernanceAddress() external view returns (address); /** * Get the time in seconds that must pass between a governance call and execution. * The timelock value can only be changed by a hardfork. */ function getTimelock() external view returns (uint256); /** * Get the addresses of the accounts that are allowed to execute the timelocked governance calls * once the timelock period expires. * Executors can be changed without a hardfork, via a normal governance call. */ function getExecutors() external view returns (address[] memory); /** * Check whether an address is one of the executors. */ function isExecutor(address _address) external view returns (bool); }
./contracts/utils/implementation/SafePct.sol
// SPDX-License-Identifier: MIT pragma solidity 0.7.6; import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol"; /** * @dev Compute percentages safely without phantom overflows. * * Intermediate operations can overflow even when the result will always * fit into computed type. Developers usually * assume that overflows raise errors. `SafePct` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafePct { using SafeMath for uint256; /** * Requirements: * * - intermediate operations must revert on overflow */ function mulDiv(uint256 x, uint256 y, uint256 z) internal pure returns (uint256) { require(z > 0, "Division by zero"); if (x == 0) return 0; uint256 xy = x * y; if (xy / x == y) { // no overflow happened - same as in SafeMath mul return xy / z; } //slither-disable-next-line divide-before-multiply uint256 a = x / z; uint256 b = x % z; // x = a * z + b //slither-disable-next-line divide-before-multiply uint256 c = y / z; uint256 d = y % z; // y = c * z + d return (a.mul(c).mul(z)).add(a.mul(d)).add(b.mul(c)).add(b.mul(d).div(z)); } }
@openzeppelin/contracts/math/SafeMath.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) return 0; uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a % b; } }
@openzeppelin/contracts/utils/ReentrancyGuard.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor () internal { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"AccountsAdded","inputs":[{"type":"address[]","name":"accounts","internalType":"address[]","indexed":false}],"anonymous":false},{"type":"event","name":"AirdropStart","inputs":[{"type":"uint256","name":"initialAirdropStartTs","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"AirdropTransferFailure","inputs":[{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"uint256","name":"amountWei","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceCallTimelocked","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"allowedAfterTimestamp","internalType":"uint256","indexed":false},{"type":"bytes","name":"encodedCall","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceInitialised","inputs":[{"type":"address","name":"initialGovernance","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"GovernedProductionModeEntered","inputs":[{"type":"address","name":"governanceSettings","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"TimelockedGovernanceCallCanceled","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TimelockedGovernanceCallExecuted","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"airdropAccounts","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"airdropAccountsLength","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"airdropAmountsWei","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cancelGovernanceCall","inputs":[{"type":"bytes4","name":"_selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executeGovernanceCall","inputs":[{"type":"bytes4","name":"_selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"governance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IGovernanceSettings"}],"name":"governanceSettings","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialAirdropStartTs","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[],"name":"initialise","inputs":[{"type":"address","name":"_governance","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"initialiseFixedAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"latestAirdropStartTs","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"nextAirdropAccountIndexToTransfer","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"productionMode","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setAirdropBalances","inputs":[{"type":"address[]","name":"_accounts","internalType":"address[]"},{"type":"uint256[]","name":"_balances","internalType":"uint256[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setAirdropStart","inputs":[{"type":"uint256","name":"_initialAirdropStartTs","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setLatestAirdropStart","inputs":[{"type":"uint256","name":"_latestAirdropStartTs","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"switchToProductionMode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"allowedAfterTimestamp","internalType":"uint256"},{"type":"bytes","name":"encodedCall","internalType":"bytes"}],"name":"timelockedCalls","inputs":[{"type":"bytes4","name":"","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalInitialAirdropWei","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalTransferredAirdropWei","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferAirdrop","inputs":[]}]
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106101375760003560e01c806374e6310e116100b8578063c9f960eb1161007c578063c9f960eb146103d7578063ce592dfb146103df578063d5261971146103e7578063e17f212e146103ef578063ea1e63211461040b578063f5a983831461043157610137565b806374e6310e146102de5780638dc7b1a91461038457806390568f81146103a15780639d6a890f146103a9578063c602a77e146103cf57610137565b80635ff27079116100ff5780635ff27079146101a757806361235585146101d057806362354e031461029257806367fc40291461029a5780636de80541146102c157610137565b80633f630c3a1461013c57806346a549b5146101565780634a4b698a1461015e5780635aa6e675146101975780635dcb01701461019f575b600080fd5b610144610439565b60408051918252519081900360200190f35b61014461043f565b61017b6004803603602081101561017457600080fd5b5035610445565b604080516001600160a01b039092168252519081900360200190f35b61017b61046f565b610144610504565b6101ce600480360360208110156101bd57600080fd5b50356001600160e01b03191661050a565b005b6101ce600480360360408110156101e657600080fd5b81019060208101813564010000000081111561020157600080fd5b82018360208201111561021357600080fd5b8035906020019184602083028401116401000000008311171561023557600080fd5b91939092909160208101903564010000000081111561025357600080fd5b82018360208201111561026557600080fd5b8035906020019184602083028401116401000000008311171561028757600080fd5b50909250905061085f565b61017b610bd5565b6101ce600480360360208110156102b057600080fd5b50356001600160e01b031916610be0565b6101ce600480360360208110156102d757600080fd5b5035610cc8565b610305600480360360208110156102f457600080fd5b50356001600160e01b031916610ed5565b6040518083815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610348578181015183820152602001610330565b50505050905090810190601f1680156103755780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b6101ce6004803603602081101561039a57600080fd5b5035610f7b565b610144611027565b6101ce600480360360208110156103bf57600080fd5b50356001600160a01b031661102d565b61014461102f565b61017b611035565b610144611055565b6101ce61105b565b6103f7611303565b604080519115158252519081900360200190f35b6101446004803603602081101561042157600080fd5b50356001600160a01b0316611313565b6101ce611325565b60055481565b60075481565b6003818154811061045557600080fd5b6000918252602090912001546001600160a01b0316905081565b60008054600160a81b900460ff16610492576000546001600160a01b03166104ff565b60076001609c1b016001600160a01b031663732524946040518163ffffffff1660e01b815260040160206040518083038186803b1580156104d257600080fd5b505afa1580156104e6573d6000803e3d6000fd5b505050506040513d60208110156104fc57600080fd5b50515b905090565b60065481565b60408051630debfda360e41b8152336004820152905160076001609c1b019163debfda30916024808301926020929190829003018186803b15801561054e57600080fd5b505afa158015610562573d6000803e3d6000fd5b505050506040513d602081101561057857600080fd5b50516105bb576040805162461bcd60e51b815260206004820152600d60248201526c37b7363c9032bc32b1baba37b960991b604482015290519081900360640190fd5b6001600160e01b0319811660009081526001602052604090208054610627576040805162461bcd60e51b815260206004820152601a60248201527f74696d656c6f636b3a20696e76616c69642073656c6563746f72000000000000604482015290519081900360640190fd5b805442101561067d576040805162461bcd60e51b815260206004820152601960248201527f74696d656c6f636b3a206e6f7420616c6c6f7765642079657400000000000000604482015290519081900360640190fd5b6000816001018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107175780601f106106ec57610100808354040283529160200191610717565b820191906000526020600020905b8154815290600101906020018083116106fa57829003601f168201915b5050506001600160e01b031986166000908152600160208190526040822082815594955090925061074b915083018261198b565b50506000805460ff60b01b1916600160b01b178155604051825130918491819060208401908083835b602083106107935780518252601f199092019160209182019101610774565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146107f5576040519150601f19603f3d011682016040523d82523d6000602084013e6107fa565b606091505b50506000805460ff60b01b19169055604080516001600160e01b03198716815242602082015281519293507fa7326b57fc9cfe267aaea5e7f0b01757154d265620a0585819416ee9ddd2c438929081900390910190a1610859816113df565b50505050565b600054600160b01b900460ff16806108815750600054600160a81b900460ff16155b15610bca5761088e6113fc565b604080518082019091526008815267746f6f206d616e7960c01b60208201526103e884111561093b5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156109005781810151838201526020016108e8565b50505050905090810190601f16801561092d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060408051808201909152601781527f617272617973206c656e67746873206d69736d6174636800000000000000000060208201528382146109be5760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156109005781810151838201526020016108e8565b5060065460408051808201909152600f81526e185b1c9958591e481cdd185c9d1959608a1b60208201529015610a355760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156109005781810151838201526020016108e8565b5060006004600086866000818110610a4957fe5b905060200201356001600160a01b03166001600160a01b03166001600160a01b03168152602001908152602001600020541115610a8557610bc5565b60005b61ffff8116841115610b6057600085858361ffff16818110610aa657fe5b905060200201356001600160a01b031690506000610ae96105dc61271087878761ffff16818110610ad357fe5b905060200201356114339092919063ffffffff16565b60038054600181019091557fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0180546001600160a01b0319166001600160a01b0385169081179091556000908152600460205260409020819055600554909150610b539082611541565b6005555050600101610a88565b507fc21490756c6f0185a8ad2363084fd0a45b06707979f77786b5e681bddc1d2fa1848460405180806020018281038252848482818152602001925060200280828437600083820152604051601f909101601f19169092018290039550909350505050a15b610859565b6108596000366115a4565b60076001609c1b0181565b610be8611727565b6001600160e01b03198116600090815260016020526040902054610c53576040805162461bcd60e51b815260206004820152601a60248201527f74696d656c6f636b3a20696e76616c69642073656c6563746f72000000000000604482015290519081900360640190fd5b604080516001600160e01b03198316815242602082015281517f7735b2391c38a81419c513e30ca578db7158eadd7101511b23e221c654d19cf8929181900390910190a16001600160e01b03198116600090815260016020819052604082208281559190610cc39083018261198b565b505050565b600054600160b01b900460ff1680610cea5750600054600160a81b900460ff16155b15610ec757610cf76113fc565b6006541580610d07575042600654115b6040518060400160405280600f81526020016e185b1c9958591e481cdd185c9d1959608a1b81525090610d7b5760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156109005781810151838201526020016108e8565b5080600654108015610d8f57506007548111155b60405180604001604052806015815260200174077726f6e672073746172742074696d657374616d7605c1b81525090610e095760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156109005781810151838201526020016108e8565b5060068190556040805182815290517fd17095b0cb6319c5430ce8553f9ce78001789e1f94f47f377653a16198f2a90b9181900360200190a147610e4b611786565b11156040518060400160405280600f81526020016e62616c616e636520746f6f206c6f7760881b81525090610ec15760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156109005781810151838201526020016108e8565b50610ed2565b610ed26000366115a4565b50565b600160208181526000928352604092839020805481840180548651600296821615610100026000190190911695909504601f81018590048502860185019096528585529094919392909190830182828015610f715780601f10610f4657610100808354040283529160200191610f71565b820191906000526020600020905b815481529060010190602001808311610f5457829003601f168201915b5050505050905082565b600054600160b01b900460ff1680610f9d5750600054600160a81b900460ff16155b15610ec757610faa6113fc565b60075460408051808201909152600b81526a185b1c9958591e481cd95d60aa1b6020820152901561101c5760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156109005781810151838201526020016108e8565b506007819055610ed2565b60085481565bfe5b60095481565b600073fffec6c83c8bf5c3f4ae0ccf8c45ce20e4560bd76104ff8161179f565b60035490565b6006541580159061106d575042600654105b6040518060400160405280600b81526020016a1b9bdd081cdd185c9d195960aa1b815250906110dd5760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156109005781810151838201526020016108e8565b50600280541415611135576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002805560095460035460009161115191603290910190611858565b6009549091505b8181101561127b5760006003828154811061116f57fe5b60009182526020808320909101546001600160a01b031680835260049091526040822080549290556003805491935090849081106111a957fe5b600091825260209091200180546001600160a01b03191690556008546111cf9082611541565b6008556040516000906001600160a01b0384169061520890849084818181858888f193505050503d8060008114611222576040519150601f19603f3d011682016040523d82523d6000602084013e611227565b606091505b5050905080611270576040805183815290516001600160a01b038516917fa63e265bae965e6aae4283d17bf7ba298580ba5924f711fe7da1a7ee4ae19ef5919081900360200190a25b505050600101611158565b5060095560016002554761128d611786565b11156040518060400160405280600f81526020016e62616c616e636520746f6f206c6f7760881b81525090610ed25760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156109005781810151838201526020016108e8565b600054600160a81b900460ff1681565b60046020526000908152604090205481565b61132d611727565b600054600160a81b900460ff161561138c576040805162461bcd60e51b815260206004820152601a60248201527f616c726561647920696e2070726f64756374696f6e206d6f6465000000000000604482015290519081900360640190fd5b60008054600161ff0160a01b031916600160a81b1790556040805160076001609c1b01815290517f83af113638b5422f9e977cebc0aaf0eaf2188eb9a8baae7f9d46c42b33a1560c9181900360200190a1565b3d604051818101604052816000823e82156113f8578181f35b8181fd5b600054600160b01b900460ff16156114295733301461141757fe5b6000805460ff60b01b19169055611431565b611431611727565b565b600080821161147c576040805162461bcd60e51b815260206004820152601060248201526f4469766973696f6e206279207a65726f60801b604482015290519081900360640190fd5b836114895750600061153a565b8383028385828161149657fe5b0414156114af578281816114a657fe5b0491505061153a565b60008386816114ba57fe5b04905060008487816114c857fe5b06905060008587816114d657fe5b04905060008688816114e457fe5b0690506115326114fe886114f8868561186e565b906118c7565b61152c61150b868661186e565b61152c611518898761186e565b61152c8d6115268c8b61186e565b9061186e565b90611541565b955050505050505b9392505050565b60008282018381101561159b576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b6115ac611727565b600082359050600060076001609c1b016001600160a01b0316636221a54b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156115f457600080fd5b505afa158015611608573d6000803e3d6000fd5b505050506040513d602081101561161e57600080fd5b505160408051808201825242830180825282516020601f89018190048102820181019094528781529394509290918281019190889088908190840183828082843760009201829052509390945250506001600160e01b031986168152600160208181526040909220845181558483015180519194506116a2939285019201906119cf565b509050507fed948300a3694aa01d4a6b258bfd664350193d770c0b51f8387277f6d83ea3b68382878760405180856001600160e01b0319168152602001848152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f191690920182900397509095505050505050a15050505050565b61172f61046f565b6001600160a01b0316336001600160a01b031614611431576040805162461bcd60e51b815260206004820152600f60248201526e6f6e6c7920676f7665726e616e636560881b604482015290519081900360640190fd5b60006104ff60085460055461192e90919063ffffffff16565b600054600160a01b900460ff16156117f5576040805162461bcd60e51b8152602060048201526014602482015273696e697469616c6973656420213d2066616c736560601b604482015290519081900360640190fd5b60008054600160a01b60ff60a01b19909116176001600160a01b0319166001600160a01b03831690811790915560408051918252517f9789733827840833afc031fb2ef9ab6894271f77bad2085687cf4ae5c7bee4db916020908290030190a150565b6000818310611867578161159b565b5090919050565b60008261187d5750600061159e565b8282028284828161188a57fe5b041461159b5760405162461bcd60e51b8152600401808060200182810382526021815260200180611a716021913960400191505060405180910390fd5b600080821161191d576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161192657fe5b049392505050565b600082821115611985576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b50805460018160011615610100020316600290046000825580601f106119b15750610ed2565b601f016020900490600052602060002090810190610ed29190611a5b565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282611a055760008555611a4b565b82601f10611a1e57805160ff1916838001178555611a4b565b82800160010185558215611a4b579182015b82811115611a4b578251825591602001919060010190611a30565b50611a57929150611a5b565b5090565b5b80821115611a575760008155600101611a5c56fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220de084bcc806438ade1d29f53684bb8a7c861697d43c2ed767e4eee2004867fda64736f6c63430007060033