diff --git a/deployments/ethereum/.chainId b/deployments/ethereum/.chainId new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/deployments/ethereum/.chainId @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/deployments/ethereum/IrrevocableVestingFactory.json b/deployments/ethereum/IrrevocableVestingFactory.json new file mode 100644 index 0000000..5948905 --- /dev/null +++ b/deployments/ethereum/IrrevocableVestingFactory.json @@ -0,0 +1,220 @@ +{ + "address": "0xDD8fb91eBdD08993218e7428Db58948e438a7aE4", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "api3Token_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "startTimestamp", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "endTimestamp", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint192", + "name": "amount", + "type": "uint192" + } + ], + "name": "DeployedIrrevocableVesting", + "type": "event" + }, + { + "inputs": [], + "name": "api3Token", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "internalType": "uint32", + "name": "startTimestamp", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "endTimestamp", + "type": "uint32" + }, + { + "internalType": "uint192", + "name": "amount", + "type": "uint192" + } + ], + "name": "deployIrrevocableVesting", + "outputs": [ + { + "internalType": "address", + "name": "irrevocableVesting", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "irrevocableVestingImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "internalType": "uint32", + "name": "startTimestamp", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "endTimestamp", + "type": "uint32" + }, + { + "internalType": "uint192", + "name": "amount", + "type": "uint192" + } + ], + "name": "predictIrrevocableVesting", + "outputs": [ + { + "internalType": "address", + "name": "irrevocableVesting", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x6d12c4bcf173c879d5ccd76fd9dee3d0dd14852d344d82fe0db8bab8659ca1db", + "receipt": { + "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "from": "0x07b589f06bD0A5324c4E2376d66d2F4F25921DE1", + "contractAddress": null, + "transactionIndex": 210, + "gasUsed": "994169", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xda274d3c8f4eee6a3835712fc7ef06ed8e5f2418afac484d6b00d6ef6ca5b20b", + "transactionHash": "0x6d12c4bcf173c879d5ccd76fd9dee3d0dd14852d344d82fe0db8bab8659ca1db", + "logs": [], + "blockNumber": 19838434, + "cumulativeGasUsed": "15863859", + "status": 1, + "byzantium": true + }, + "args": ["0x0b38210ea11411557c13457D4dA7dC6ea731B88a"], + "numDeployments": 1, + "solcInputHash": "124e6d9136e32d944e58f6fcf4fd6111", + "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"api3Token_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"startTimestamp\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"endTimestamp\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint192\",\"name\":\"amount\",\"type\":\"uint192\"}],\"name\":\"DeployedIrrevocableVesting\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"api3Token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"startTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"endTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint192\",\"name\":\"amount\",\"type\":\"uint192\"}],\"name\":\"deployIrrevocableVesting\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"irrevocableVesting\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"irrevocableVestingImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"startTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"endTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint192\",\"name\":\"amount\",\"type\":\"uint192\"}],\"name\":\"predictIrrevocableVesting\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"irrevocableVesting\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"api3Token_\":\"Api3Token address\"}},\"deployIrrevocableVesting(address,uint32,uint32,uint192)\":{\"details\":\"The sender needs to approve `amount` API3 tokens to this contract before calling this function\",\"params\":{\"amount\":\"Amount of tokens to be vested over the period\",\"beneficiary\":\"Beneficiary of the vesting\",\"endTimestamp\":\"Ending timestamp of the vesting\",\"startTimestamp\":\"Starting timestamp of the vesting\"},\"returns\":{\"irrevocableVesting\":\"IrrevocableVesting clone address\"}},\"predictIrrevocableVesting(address,uint32,uint32,uint192)\":{\"params\":{\"amount\":\"Amount of tokens to be vested over the period\",\"beneficiary\":\"Beneficiary of the vesting\",\"endTimestamp\":\"Ending timestamp of the vesting\",\"startTimestamp\":\"Starting timestamp of the vesting\"},\"returns\":{\"irrevocableVesting\":\"IrrevocableVesting clone address\"}}},\"title\":\"Contract that deploys an IrrevocableVesting implementation and allows it to be cloned to create vestings\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"api3Token()\":{\"notice\":\"Api3Token address\"},\"deployIrrevocableVesting(address,uint32,uint32,uint192)\":{\"notice\":\"Deploys an IrrevocableVesting clone and transfers the vesting amount to it from the sender\"},\"irrevocableVestingImplementation()\":{\"notice\":\"IrrevocableVesting implementation address\"},\"predictIrrevocableVesting(address,uint32,uint32,uint192)\":{\"notice\":\"Predicts the address of the IrrevocableVesting clone that would be deployed by this contract\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/IrrevocableVestingFactory.sol\":\"IrrevocableVestingFactory\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/proxy/Clones.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/Clones.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\\n * deploying minimal proxy contracts, also known as \\\"clones\\\".\\n *\\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\\n *\\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\\n * deterministic method.\\n *\\n * _Available since v3.4._\\n */\\nlibrary Clones {\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\\n *\\n * This function uses the create opcode, which should never revert.\\n */\\n function clone(address implementation) internal returns (address instance) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes\\n // of the `implementation` address with the bytecode before the address.\\n mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))\\n // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.\\n mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))\\n instance := create(0, 0x09, 0x37)\\n }\\n require(instance != address(0), \\\"ERC1167: create failed\\\");\\n }\\n\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\\n *\\n * This function uses the create2 opcode and a `salt` to deterministically deploy\\n * the clone. Using the same `implementation` and `salt` multiple time will revert, since\\n * the clones cannot be deployed twice at the same address.\\n */\\n function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes\\n // of the `implementation` address with the bytecode before the address.\\n mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))\\n // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.\\n mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))\\n instance := create2(0, 0x09, 0x37, salt)\\n }\\n require(instance != address(0), \\\"ERC1167: create2 failed\\\");\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(\\n address implementation,\\n bytes32 salt,\\n address deployer\\n ) internal pure returns (address predicted) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let ptr := mload(0x40)\\n mstore(add(ptr, 0x38), deployer)\\n mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff)\\n mstore(add(ptr, 0x14), implementation)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73)\\n mstore(add(ptr, 0x58), salt)\\n mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37))\\n predicted := keccak256(add(ptr, 0x43), 0x55)\\n }\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(\\n address implementation,\\n bytes32 salt\\n ) internal view returns (address predicted) {\\n return predictDeterministicAddress(implementation, salt, address(this));\\n }\\n}\\n\",\"keccak256\":\"0x01f055f5c26ba25d7f83e9aa9ba877fbea4d0bf22227de046ea67494bc932999\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"contracts/IrrevocableVesting.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./interfaces/IIrrevocableVesting.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title Contract that implements an irrevocable vesting of API3 tokens\\n/// allocated to a beneficiary\\n/// @notice This contract is an implementation that is required to be cloned by\\n/// a IrrevocableVestingFactory contract. The beneficiary of the vesting is\\n/// expected to interact with this contract through a generic, ABI-based UI\\n/// such as Etherscan's. See the repo's README for instructions.\\ncontract IrrevocableVesting is IIrrevocableVesting {\\n struct Vesting {\\n uint32 startTimestamp;\\n uint32 endTimestamp;\\n uint192 amount;\\n }\\n\\n /// @notice Api3Token address\\n address public immutable override api3Token;\\n\\n /// @notice Beneficiary of the vesting\\n address public override beneficiary;\\n\\n /// @notice Vesting parameters, including the schedule and the amount\\n Vesting public override vesting;\\n\\n /// @dev Prevents tokens from being locked by setting an unreasonably late\\n /// vesting end timestamp. The vesting periods are expected to be 4 years,\\n /// and we have 1 year of buffer here in case the vesting is required to\\n /// start in the future.\\n uint256\\n private constant MAXIMUM_TIME_BETWEEN_INITIALIZATION_AND_VESTING_END =\\n 5 * 365 days;\\n\\n /// @dev Reverts if the sender is not the beneficiary\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"Sender not beneficiary\\\");\\n _;\\n }\\n\\n /// @dev This contract is means to be an implementation for\\n /// IrrevocableVestingFactory to clone. To prevent the implementation from\\n /// being used, the contract is rendered uninitializable.\\n /// @param api3Token_ Api3Token address\\n constructor(address api3Token_) {\\n require(api3Token_ != address(0), \\\"Api3Token address zero\\\");\\n api3Token = api3Token_;\\n beneficiary = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF;\\n }\\n\\n /// @notice Initializes a newly cloned IrrevocableVesting\\n /// @dev Since beneficiary is required to be zero address, only clones of\\n /// this contract can be initialized.\\n /// Anyone can initialize a IrrevocableVesting clone. The user is required\\n /// to prevent others from initializing their clones, for example, by\\n /// initializing the clone in the same transaction as it is deployed in.\\n /// The IrrevocableVesting needs to have exactly `amount` API3 tokens.\\n /// @param beneficiary_ Beneficiary of the vesting\\n /// @param startTimestamp Starting timestamp of the vesting\\n /// @param endTimestamp Ending timestamp of the vesting\\n /// @param amount Amount of tokens to be vested over the period\\n function initialize(\\n address beneficiary_,\\n uint32 startTimestamp,\\n uint32 endTimestamp,\\n uint192 amount\\n ) external override {\\n require(beneficiary == address(0), \\\"Already initialized\\\");\\n require(beneficiary_ != address(0), \\\"Beneficiary address zero\\\");\\n require(startTimestamp != 0, \\\"Start timestamp zero\\\");\\n require(endTimestamp > startTimestamp, \\\"End not later than start\\\");\\n require(\\n endTimestamp <=\\n block.timestamp +\\n MAXIMUM_TIME_BETWEEN_INITIALIZATION_AND_VESTING_END,\\n \\\"End is too far in the future\\\"\\n );\\n require(amount != 0, \\\"Amount zero\\\");\\n require(\\n IERC20(api3Token).balanceOf(address(this)) == amount,\\n \\\"Balance is not vesting amount\\\"\\n );\\n beneficiary = beneficiary_;\\n vesting = Vesting({\\n startTimestamp: startTimestamp,\\n endTimestamp: endTimestamp,\\n amount: amount\\n });\\n }\\n\\n /// @notice Called by the beneficiary to withdraw as many tokens the\\n /// vesting schedule allows\\n function withdrawAsBeneficiary() external override onlyBeneficiary {\\n uint256 balance = IERC20(api3Token).balanceOf(address(this));\\n require(balance != 0, \\\"Balance zero\\\");\\n uint256 unvestedAmountInBalance = unvestedAmount();\\n require(\\n balance > unvestedAmountInBalance,\\n \\\"Tokens in balance not vested yet\\\"\\n );\\n uint256 withdrawalAmount = balance - unvestedAmountInBalance;\\n IERC20(api3Token).transfer(msg.sender, withdrawalAmount);\\n emit WithdrawnAsBeneficiary(withdrawalAmount);\\n }\\n\\n /// @notice Returns the amount of tokens that are yet to be vested based on\\n /// the schedule\\n /// @return Amount of unvested tokens\\n function unvestedAmount() public view override returns (uint256) {\\n (uint32 startTimestamp, uint32 endTimestamp, uint192 amount) = (\\n vesting.startTimestamp,\\n vesting.endTimestamp,\\n vesting.amount\\n );\\n if (block.timestamp <= startTimestamp) {\\n return amount;\\n } else if (block.timestamp >= endTimestamp) {\\n return 0;\\n } else {\\n uint256 passedTime = block.timestamp - startTimestamp;\\n uint256 totalTime = endTimestamp - startTimestamp;\\n return amount - (amount * passedTime) / totalTime;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7ba9f5696c4f1df17aefd2e27d89c667543e3bfb422a5e388f21107276747ac6\",\"license\":\"MIT\"},\"contracts/IrrevocableVestingFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./interfaces/IIrrevocableVestingFactory.sol\\\";\\nimport \\\"./IrrevocableVesting.sol\\\";\\nimport \\\"@openzeppelin/contracts/proxy/Clones.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @title Contract that deploys an IrrevocableVesting implementation and\\n/// allows it to be cloned to create vestings\\ncontract IrrevocableVestingFactory is IIrrevocableVestingFactory {\\n /// @notice Api3Token address\\n address public immutable override api3Token;\\n\\n /// @notice IrrevocableVesting implementation address\\n address public immutable override irrevocableVestingImplementation;\\n\\n /// @param api3Token_ Api3Token address\\n constructor(address api3Token_) {\\n require(api3Token_ != address(0), \\\"Api3Token address zero\\\");\\n api3Token = api3Token_;\\n irrevocableVestingImplementation = address(\\n new IrrevocableVesting(api3Token_)\\n );\\n }\\n\\n /// @notice Deploys an IrrevocableVesting clone and transfers the vesting\\n /// amount to it from the sender\\n /// @dev The sender needs to approve `amount` API3 tokens to this contract\\n /// before calling this function\\n /// @param beneficiary Beneficiary of the vesting\\n /// @param startTimestamp Starting timestamp of the vesting\\n /// @param endTimestamp Ending timestamp of the vesting\\n /// @param amount Amount of tokens to be vested over the period\\n /// @return irrevocableVesting IrrevocableVesting clone address\\n function deployIrrevocableVesting(\\n address beneficiary,\\n uint32 startTimestamp,\\n uint32 endTimestamp,\\n uint192 amount\\n ) external override returns (address irrevocableVesting) {\\n irrevocableVesting = Clones.cloneDeterministic(\\n irrevocableVestingImplementation,\\n keccak256(\\n abi.encodePacked(\\n beneficiary,\\n startTimestamp,\\n endTimestamp,\\n amount\\n )\\n )\\n );\\n IERC20(api3Token).transferFrom(msg.sender, irrevocableVesting, amount);\\n IIrrevocableVesting(irrevocableVesting).initialize(\\n beneficiary,\\n startTimestamp,\\n endTimestamp,\\n amount\\n );\\n emit DeployedIrrevocableVesting(\\n beneficiary,\\n startTimestamp,\\n endTimestamp,\\n amount\\n );\\n }\\n\\n /// @notice Predicts the address of the IrrevocableVesting clone that would\\n /// be deployed by this contract\\n /// @param beneficiary Beneficiary of the vesting\\n /// @param startTimestamp Starting timestamp of the vesting\\n /// @param endTimestamp Ending timestamp of the vesting\\n /// @param amount Amount of tokens to be vested over the period\\n /// @return irrevocableVesting IrrevocableVesting clone address\\n function predictIrrevocableVesting(\\n address beneficiary,\\n uint32 startTimestamp,\\n uint32 endTimestamp,\\n uint192 amount\\n ) external view override returns (address irrevocableVesting) {\\n irrevocableVesting = Clones.predictDeterministicAddress(\\n irrevocableVestingImplementation,\\n keccak256(\\n abi.encodePacked(\\n beneficiary,\\n startTimestamp,\\n endTimestamp,\\n amount\\n )\\n )\\n );\\n }\\n}\\n\",\"keccak256\":\"0x85596cf9bce37d6fe0caf264124ce4345a923ac6784a4606b634510812d97d6d\",\"license\":\"MIT\"},\"contracts/interfaces/IIrrevocableVesting.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IIrrevocableVesting {\\n event WithdrawnAsBeneficiary(uint256 amount);\\n\\n function initialize(\\n address beneficiary_,\\n uint32 startTimestamp,\\n uint32 endTimestamp,\\n uint192 amount\\n ) external;\\n\\n function withdrawAsBeneficiary() external;\\n\\n function unvestedAmount() external view returns (uint256);\\n\\n function api3Token() external returns (address);\\n\\n function beneficiary() external returns (address);\\n\\n function vesting()\\n external\\n returns (uint32 startTimestamp, uint32 endTimestamp, uint192 amount);\\n}\\n\",\"keccak256\":\"0x0bca81443185b8a71a034c94dcd35492bc8f430cf6c4d343cbd167bb59a8c471\",\"license\":\"MIT\"},\"contracts/interfaces/IIrrevocableVestingFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IIrrevocableVestingFactory {\\n event DeployedIrrevocableVesting(\\n address indexed beneficiary,\\n uint32 startTimestamp,\\n uint32 endTimestamp,\\n uint192 amount\\n );\\n\\n function deployIrrevocableVesting(\\n address beneficiary,\\n uint32 startTimestamp,\\n uint32 endTimestamp,\\n uint192 amount\\n ) external returns (address irrevocableVesting);\\n\\n function predictIrrevocableVesting(\\n address beneficiary,\\n uint32 startTimestamp,\\n uint32 endTimestamp,\\n uint192 amount\\n ) external returns (address irrevocableVesting);\\n\\n function api3Token() external returns (address);\\n\\n function irrevocableVestingImplementation() external returns (address);\\n}\\n\",\"keccak256\":\"0xfb924d577ee4a800f635e6d102c0a3916ae7b05a24c16b601d15b6cae09a80c8\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c060405234801561001057600080fd5b5060405161125838038061125883398101604081905261002f916100f0565b6001600160a01b0381166100895760405162461bcd60e51b815260206004820152601660248201527f41706933546f6b656e2061646472657373207a65726f00000000000000000000604482015260640160405180910390fd5b6001600160a01b03811660805260405181906100a4906100e3565b6001600160a01b039091168152602001604051809103906000f0801580156100d0573d6000803e3d6000fd5b506001600160a01b031660a05250610120565b610afa8061075e83390190565b60006020828403121561010257600080fd5b81516001600160a01b038116811461011957600080fd5b9392505050565b60805160a05161060661015860003960008181605601528181610153015261020c0152600081816099015261029a01526106066000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632d9c2fa914610051578063613d517d14610094578063847dbfc6146100bb578063cc72f8f1146100ce575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6100786100c9366004610537565b6100e1565b6100786100dc366004610537565b61019a565b60408051606086901b6bffffffffffffffffffffffff1916602082015260e085811b7fffffffff0000000000000000000000000000000000000000000000000000000090811660348401529085901b1660388201529082901b67ffffffffffffffff1916603c820152600090610191907f00000000000000000000000000000000000000000000000000000000000000009060540160405160208183030381529060405280519060200120610404565b95945050505050565b60408051606086901b6bffffffffffffffffffffffff1916602082015260e085811b7fffffffff0000000000000000000000000000000000000000000000000000000090811660348401529085901b1660388201529082901b67ffffffffffffffff1916603c82015260009061024a907f00000000000000000000000000000000000000000000000000000000000000009060540160405160208183030381529060405280519060200120610463565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0380831660248301526001600160c01b03851660448301529192507f0000000000000000000000000000000000000000000000000000000000000000909116906323b872dd906064016020604051808303816000875af11580156102e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030991906105a7565b506040517f3630112a0000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015263ffffffff8087166024840152851660448301526001600160c01b0384166064830152821690633630112a90608401600060405180830381600087803b15801561038957600080fd5b505af115801561039d573d6000803e3d6000fd5b50506040805163ffffffff8881168252871660208201526001600160c01b0386168183015290516001600160a01b03891693507f880d585f4d20e0511ae522d17f588cc5649bfe81b1120545eba6383c29046e1392509081900360600190a2949350505050565b6040513060388201526f5af43d82803e903d91602b57fd5bf3ff602482015260148101839052733d602d80600a3d3981f3363d3d373d3d3d363d738152605881018290526037600c820120607882015260556043909101205b92915050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b03811661045d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f455243313136373a2063726561746532206661696c6564000000000000000000604482015260640160405180910390fd5b803563ffffffff8116811461053257600080fd5b919050565b6000806000806080858703121561054d57600080fd5b84356001600160a01b038116811461056457600080fd5b93506105726020860161051e565b92506105806040860161051e565b915060608501356001600160c01b038116811461059c57600080fd5b939692955090935050565b6000602082840312156105b957600080fd5b815180151581146105c957600080fd5b939250505056fea2646970667358221220a6289ee443a5593970c8f9274e2a485c17481833d927f65438b95e2f1ac62bb864736f6c6343000811003360a060405234801561001057600080fd5b50604051610afa380380610afa83398101604081905261002f916100af565b6001600160a01b0381166100895760405162461bcd60e51b815260206004820152601660248201527f41706933546f6b656e2061646472657373207a65726f00000000000000000000604482015260640160405180910390fd5b6001600160a01b03908116608052600080546001600160a01b03191690911790556100df565b6000602082840312156100c157600080fd5b81516001600160a01b03811681146100d857600080fd5b9392505050565b6080516109eb61010f60003960008181610121015281816103a201528181610639015261079d01526109eb6000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063613d517d11610050578063613d517d1461011c578063d950975a14610143578063e13b0f741461015957600080fd5b80633630112a1461007757806338af3eed1461008c57806344c63eec146100bc575b600080fd5b61008a610085366004610864565b610161565b005b60005461009f906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6001546100f09063ffffffff808216916401000000008104909116906801000000000000000090046001600160c01b031683565b6040805163ffffffff94851681529390921660208401526001600160c01b0316908201526060016100b3565b61009f7f000000000000000000000000000000000000000000000000000000000000000081565b61014b610506565b6040519081526020016100b3565b61008a6105c7565b6000546001600160a01b0316156101bf5760405162461bcd60e51b815260206004820152601360248201527f416c726561647920696e697469616c697a65640000000000000000000000000060448201526064015b60405180910390fd5b6001600160a01b0384166102155760405162461bcd60e51b815260206004820152601860248201527f42656e65666963696172792061646472657373207a65726f000000000000000060448201526064016101b6565b8263ffffffff1660000361026b5760405162461bcd60e51b815260206004820152601460248201527f53746172742074696d657374616d70207a65726f00000000000000000000000060448201526064016101b6565b8263ffffffff168263ffffffff16116102c65760405162461bcd60e51b815260206004820152601860248201527f456e64206e6f74206c61746572207468616e207374617274000000000000000060448201526064016101b6565b6102d46309660180426108ea565b8263ffffffff1611156103295760405162461bcd60e51b815260206004820152601c60248201527f456e6420697320746f6f2066617220696e20746865206675747572650000000060448201526064016101b6565b806001600160c01b03166000036103825760405162461bcd60e51b815260206004820152600b60248201527f416d6f756e74207a65726f00000000000000000000000000000000000000000060448201526064016101b6565b6040516370a0823160e01b81523060048201526001600160c01b038216907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156103f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104159190610903565b146104625760405162461bcd60e51b815260206004820152601d60248201527f42616c616e6365206973206e6f742076657374696e6720616d6f756e7400000060448201526064016101b6565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0395909516949094179093556040805160608101825263ffffffff93841680825292909316602084018190526001600160c01b0390941692018290526001805467ffffffffffffffff19169091176401000000009093029290921767ffffffffffffffff1668010000000000000000909102179055565b60015460009063ffffffff808216916401000000008104909116906801000000000000000090046001600160c01b031642831061054d576001600160c01b03169392505050565b8163ffffffff164210610564576000935050505090565b600061057663ffffffff85164261091c565b90506000610584858561092f565b63ffffffff169050806105a0836001600160c01b038616610953565b6105aa919061096a565b6105bd906001600160c01b03851661091c565b9550505050505090565b6000546001600160a01b031633146106215760405162461bcd60e51b815260206004820152601660248201527f53656e646572206e6f742062656e65666963696172790000000000000000000060448201526064016101b6565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610688573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ac9190610903565b9050806000036106fe5760405162461bcd60e51b815260206004820152600c60248201527f42616c616e6365207a65726f000000000000000000000000000000000000000060448201526064016101b6565b6000610708610506565b90508082116107595760405162461bcd60e51b815260206004820181905260248201527f546f6b656e7320696e2062616c616e6365206e6f74207665737465642079657460448201526064016101b6565b6000610765828461091c565b6040517fa9059cbb000000000000000000000000000000000000000000000000000000008152336004820152602481018290529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af11580156107ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610812919061098c565b506040518181527fee57bdaf2480573432b9ff9ca4adb3a104d5e016f87db391ab72bea5acc843829060200160405180910390a1505050565b803563ffffffff8116811461085f57600080fd5b919050565b6000806000806080858703121561087a57600080fd5b84356001600160a01b038116811461089157600080fd5b935061089f6020860161084b565b92506108ad6040860161084b565b915060608501356001600160c01b03811681146108c957600080fd5b939692955090935050565b634e487b7160e01b600052601160045260246000fd5b808201808211156108fd576108fd6108d4565b92915050565b60006020828403121561091557600080fd5b5051919050565b818103818111156108fd576108fd6108d4565b63ffffffff82811682821603908082111561094c5761094c6108d4565b5092915050565b80820281158282048414176108fd576108fd6108d4565b60008261098757634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561099e57600080fd5b815180151581146109ae57600080fd5b939250505056fea26469706673582212201e0293d6d41893cd6bc28c4d4c564cd659e17315ba7a4615afa497acedc570bb64736f6c63430008110033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632d9c2fa914610051578063613d517d14610094578063847dbfc6146100bb578063cc72f8f1146100ce575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6100786100c9366004610537565b6100e1565b6100786100dc366004610537565b61019a565b60408051606086901b6bffffffffffffffffffffffff1916602082015260e085811b7fffffffff0000000000000000000000000000000000000000000000000000000090811660348401529085901b1660388201529082901b67ffffffffffffffff1916603c820152600090610191907f00000000000000000000000000000000000000000000000000000000000000009060540160405160208183030381529060405280519060200120610404565b95945050505050565b60408051606086901b6bffffffffffffffffffffffff1916602082015260e085811b7fffffffff0000000000000000000000000000000000000000000000000000000090811660348401529085901b1660388201529082901b67ffffffffffffffff1916603c82015260009061024a907f00000000000000000000000000000000000000000000000000000000000000009060540160405160208183030381529060405280519060200120610463565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0380831660248301526001600160c01b03851660448301529192507f0000000000000000000000000000000000000000000000000000000000000000909116906323b872dd906064016020604051808303816000875af11580156102e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030991906105a7565b506040517f3630112a0000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015263ffffffff8087166024840152851660448301526001600160c01b0384166064830152821690633630112a90608401600060405180830381600087803b15801561038957600080fd5b505af115801561039d573d6000803e3d6000fd5b50506040805163ffffffff8881168252871660208201526001600160c01b0386168183015290516001600160a01b03891693507f880d585f4d20e0511ae522d17f588cc5649bfe81b1120545eba6383c29046e1392509081900360600190a2949350505050565b6040513060388201526f5af43d82803e903d91602b57fd5bf3ff602482015260148101839052733d602d80600a3d3981f3363d3d373d3d3d363d738152605881018290526037600c820120607882015260556043909101205b92915050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b03811661045d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f455243313136373a2063726561746532206661696c6564000000000000000000604482015260640160405180910390fd5b803563ffffffff8116811461053257600080fd5b919050565b6000806000806080858703121561054d57600080fd5b84356001600160a01b038116811461056457600080fd5b93506105726020860161051e565b92506105806040860161051e565b915060608501356001600160c01b038116811461059c57600080fd5b939692955090935050565b6000602082840312156105b957600080fd5b815180151581146105c957600080fd5b939250505056fea2646970667358221220a6289ee443a5593970c8f9274e2a485c17481833d927f65438b95e2f1ac62bb864736f6c63430008110033", + "devdoc": { + "kind": "dev", + "methods": { + "constructor": { + "params": { + "api3Token_": "Api3Token address" + } + }, + "deployIrrevocableVesting(address,uint32,uint32,uint192)": { + "details": "The sender needs to approve `amount` API3 tokens to this contract before calling this function", + "params": { + "amount": "Amount of tokens to be vested over the period", + "beneficiary": "Beneficiary of the vesting", + "endTimestamp": "Ending timestamp of the vesting", + "startTimestamp": "Starting timestamp of the vesting" + }, + "returns": { + "irrevocableVesting": "IrrevocableVesting clone address" + } + }, + "predictIrrevocableVesting(address,uint32,uint32,uint192)": { + "params": { + "amount": "Amount of tokens to be vested over the period", + "beneficiary": "Beneficiary of the vesting", + "endTimestamp": "Ending timestamp of the vesting", + "startTimestamp": "Starting timestamp of the vesting" + }, + "returns": { + "irrevocableVesting": "IrrevocableVesting clone address" + } + } + }, + "title": "Contract that deploys an IrrevocableVesting implementation and allows it to be cloned to create vestings", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "api3Token()": { + "notice": "Api3Token address" + }, + "deployIrrevocableVesting(address,uint32,uint32,uint192)": { + "notice": "Deploys an IrrevocableVesting clone and transfers the vesting amount to it from the sender" + }, + "irrevocableVestingImplementation()": { + "notice": "IrrevocableVesting implementation address" + }, + "predictIrrevocableVesting(address,uint32,uint32,uint192)": { + "notice": "Predicts the address of the IrrevocableVesting clone that would be deployed by this contract" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/ethereum/solcInputs/124e6d9136e32d944e58f6fcf4fd6111.json b/deployments/ethereum/solcInputs/124e6d9136e32d944e58f6fcf4fd6111.json new file mode 100644 index 0000000..a37a764 --- /dev/null +++ b/deployments/ethereum/solcInputs/124e6d9136e32d944e58f6fcf4fd6111.json @@ -0,0 +1,63 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/proxy/Clones.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/Clones.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\n * deploying minimal proxy contracts, also known as \"clones\".\n *\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\n *\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\n * deterministic method.\n *\n * _Available since v3.4._\n */\nlibrary Clones {\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\n *\n * This function uses the create opcode, which should never revert.\n */\n function clone(address implementation) internal returns (address instance) {\n /// @solidity memory-safe-assembly\n assembly {\n // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes\n // of the `implementation` address with the bytecode before the address.\n mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))\n // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.\n mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))\n instance := create(0, 0x09, 0x37)\n }\n require(instance != address(0), \"ERC1167: create failed\");\n }\n\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\n *\n * This function uses the create2 opcode and a `salt` to deterministically deploy\n * the clone. Using the same `implementation` and `salt` multiple time will revert, since\n * the clones cannot be deployed twice at the same address.\n */\n function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {\n /// @solidity memory-safe-assembly\n assembly {\n // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes\n // of the `implementation` address with the bytecode before the address.\n mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))\n // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.\n mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))\n instance := create2(0, 0x09, 0x37, salt)\n }\n require(instance != address(0), \"ERC1167: create2 failed\");\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(\n address implementation,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(add(ptr, 0x38), deployer)\n mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff)\n mstore(add(ptr, 0x14), implementation)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73)\n mstore(add(ptr, 0x58), salt)\n mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37))\n predicted := keccak256(add(ptr, 0x43), 0x55)\n }\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(\n address implementation,\n bytes32 salt\n ) internal view returns (address predicted) {\n return predictDeterministicAddress(implementation, salt, address(this));\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the default value returned by this function, unless\n * it's overridden.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(address from, address to, uint256 amount) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n" + }, + "contracts/interfaces/IIrrevocableVesting.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IIrrevocableVesting {\n event WithdrawnAsBeneficiary(uint256 amount);\n\n function initialize(\n address beneficiary_,\n uint32 startTimestamp,\n uint32 endTimestamp,\n uint192 amount\n ) external;\n\n function withdrawAsBeneficiary() external;\n\n function unvestedAmount() external view returns (uint256);\n\n function api3Token() external returns (address);\n\n function beneficiary() external returns (address);\n\n function vesting()\n external\n returns (uint32 startTimestamp, uint32 endTimestamp, uint192 amount);\n}\n" + }, + "contracts/interfaces/IIrrevocableVestingFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IIrrevocableVestingFactory {\n event DeployedIrrevocableVesting(\n address indexed beneficiary,\n uint32 startTimestamp,\n uint32 endTimestamp,\n uint192 amount\n );\n\n function deployIrrevocableVesting(\n address beneficiary,\n uint32 startTimestamp,\n uint32 endTimestamp,\n uint192 amount\n ) external returns (address irrevocableVesting);\n\n function predictIrrevocableVesting(\n address beneficiary,\n uint32 startTimestamp,\n uint32 endTimestamp,\n uint192 amount\n ) external returns (address irrevocableVesting);\n\n function api3Token() external returns (address);\n\n function irrevocableVestingImplementation() external returns (address);\n}\n" + }, + "contracts/IrrevocableVesting.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./interfaces/IIrrevocableVesting.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/// @title Contract that implements an irrevocable vesting of API3 tokens\n/// allocated to a beneficiary\n/// @notice This contract is an implementation that is required to be cloned by\n/// a IrrevocableVestingFactory contract. The beneficiary of the vesting is\n/// expected to interact with this contract through a generic, ABI-based UI\n/// such as Etherscan's. See the repo's README for instructions.\ncontract IrrevocableVesting is IIrrevocableVesting {\n struct Vesting {\n uint32 startTimestamp;\n uint32 endTimestamp;\n uint192 amount;\n }\n\n /// @notice Api3Token address\n address public immutable override api3Token;\n\n /// @notice Beneficiary of the vesting\n address public override beneficiary;\n\n /// @notice Vesting parameters, including the schedule and the amount\n Vesting public override vesting;\n\n /// @dev Prevents tokens from being locked by setting an unreasonably late\n /// vesting end timestamp. The vesting periods are expected to be 4 years,\n /// and we have 1 year of buffer here in case the vesting is required to\n /// start in the future.\n uint256\n private constant MAXIMUM_TIME_BETWEEN_INITIALIZATION_AND_VESTING_END =\n 5 * 365 days;\n\n /// @dev Reverts if the sender is not the beneficiary\n modifier onlyBeneficiary() {\n require(msg.sender == beneficiary, \"Sender not beneficiary\");\n _;\n }\n\n /// @dev This contract is means to be an implementation for\n /// IrrevocableVestingFactory to clone. To prevent the implementation from\n /// being used, the contract is rendered uninitializable.\n /// @param api3Token_ Api3Token address\n constructor(address api3Token_) {\n require(api3Token_ != address(0), \"Api3Token address zero\");\n api3Token = api3Token_;\n beneficiary = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF;\n }\n\n /// @notice Initializes a newly cloned IrrevocableVesting\n /// @dev Since beneficiary is required to be zero address, only clones of\n /// this contract can be initialized.\n /// Anyone can initialize a IrrevocableVesting clone. The user is required\n /// to prevent others from initializing their clones, for example, by\n /// initializing the clone in the same transaction as it is deployed in.\n /// The IrrevocableVesting needs to have exactly `amount` API3 tokens.\n /// @param beneficiary_ Beneficiary of the vesting\n /// @param startTimestamp Starting timestamp of the vesting\n /// @param endTimestamp Ending timestamp of the vesting\n /// @param amount Amount of tokens to be vested over the period\n function initialize(\n address beneficiary_,\n uint32 startTimestamp,\n uint32 endTimestamp,\n uint192 amount\n ) external override {\n require(beneficiary == address(0), \"Already initialized\");\n require(beneficiary_ != address(0), \"Beneficiary address zero\");\n require(startTimestamp != 0, \"Start timestamp zero\");\n require(endTimestamp > startTimestamp, \"End not later than start\");\n require(\n endTimestamp <=\n block.timestamp +\n MAXIMUM_TIME_BETWEEN_INITIALIZATION_AND_VESTING_END,\n \"End is too far in the future\"\n );\n require(amount != 0, \"Amount zero\");\n require(\n IERC20(api3Token).balanceOf(address(this)) == amount,\n \"Balance is not vesting amount\"\n );\n beneficiary = beneficiary_;\n vesting = Vesting({\n startTimestamp: startTimestamp,\n endTimestamp: endTimestamp,\n amount: amount\n });\n }\n\n /// @notice Called by the beneficiary to withdraw as many tokens the\n /// vesting schedule allows\n function withdrawAsBeneficiary() external override onlyBeneficiary {\n uint256 balance = IERC20(api3Token).balanceOf(address(this));\n require(balance != 0, \"Balance zero\");\n uint256 unvestedAmountInBalance = unvestedAmount();\n require(\n balance > unvestedAmountInBalance,\n \"Tokens in balance not vested yet\"\n );\n uint256 withdrawalAmount = balance - unvestedAmountInBalance;\n IERC20(api3Token).transfer(msg.sender, withdrawalAmount);\n emit WithdrawnAsBeneficiary(withdrawalAmount);\n }\n\n /// @notice Returns the amount of tokens that are yet to be vested based on\n /// the schedule\n /// @return Amount of unvested tokens\n function unvestedAmount() public view override returns (uint256) {\n (uint32 startTimestamp, uint32 endTimestamp, uint192 amount) = (\n vesting.startTimestamp,\n vesting.endTimestamp,\n vesting.amount\n );\n if (block.timestamp <= startTimestamp) {\n return amount;\n } else if (block.timestamp >= endTimestamp) {\n return 0;\n } else {\n uint256 passedTime = block.timestamp - startTimestamp;\n uint256 totalTime = endTimestamp - startTimestamp;\n return amount - (amount * passedTime) / totalTime;\n }\n }\n}\n" + }, + "contracts/IrrevocableVestingFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./interfaces/IIrrevocableVestingFactory.sol\";\nimport \"./IrrevocableVesting.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/// @title Contract that deploys an IrrevocableVesting implementation and\n/// allows it to be cloned to create vestings\ncontract IrrevocableVestingFactory is IIrrevocableVestingFactory {\n /// @notice Api3Token address\n address public immutable override api3Token;\n\n /// @notice IrrevocableVesting implementation address\n address public immutable override irrevocableVestingImplementation;\n\n /// @param api3Token_ Api3Token address\n constructor(address api3Token_) {\n require(api3Token_ != address(0), \"Api3Token address zero\");\n api3Token = api3Token_;\n irrevocableVestingImplementation = address(\n new IrrevocableVesting(api3Token_)\n );\n }\n\n /// @notice Deploys an IrrevocableVesting clone and transfers the vesting\n /// amount to it from the sender\n /// @dev The sender needs to approve `amount` API3 tokens to this contract\n /// before calling this function\n /// @param beneficiary Beneficiary of the vesting\n /// @param startTimestamp Starting timestamp of the vesting\n /// @param endTimestamp Ending timestamp of the vesting\n /// @param amount Amount of tokens to be vested over the period\n /// @return irrevocableVesting IrrevocableVesting clone address\n function deployIrrevocableVesting(\n address beneficiary,\n uint32 startTimestamp,\n uint32 endTimestamp,\n uint192 amount\n ) external override returns (address irrevocableVesting) {\n irrevocableVesting = Clones.cloneDeterministic(\n irrevocableVestingImplementation,\n keccak256(\n abi.encodePacked(\n beneficiary,\n startTimestamp,\n endTimestamp,\n amount\n )\n )\n );\n IERC20(api3Token).transferFrom(msg.sender, irrevocableVesting, amount);\n IIrrevocableVesting(irrevocableVesting).initialize(\n beneficiary,\n startTimestamp,\n endTimestamp,\n amount\n );\n emit DeployedIrrevocableVesting(\n beneficiary,\n startTimestamp,\n endTimestamp,\n amount\n );\n }\n\n /// @notice Predicts the address of the IrrevocableVesting clone that would\n /// be deployed by this contract\n /// @param beneficiary Beneficiary of the vesting\n /// @param startTimestamp Starting timestamp of the vesting\n /// @param endTimestamp Ending timestamp of the vesting\n /// @param amount Amount of tokens to be vested over the period\n /// @return irrevocableVesting IrrevocableVesting clone address\n function predictIrrevocableVesting(\n address beneficiary,\n uint32 startTimestamp,\n uint32 endTimestamp,\n uint192 amount\n ) external view override returns (address irrevocableVesting) {\n irrevocableVesting = Clones.predictDeterministicAddress(\n irrevocableVestingImplementation,\n keccak256(\n abi.encodePacked(\n beneficiary,\n startTimestamp,\n endTimestamp,\n amount\n )\n )\n );\n }\n}\n" + }, + "contracts/mock/BadStakeableVestingFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"../IrrevocableVesting.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ncontract BadIrrevocableVestingFactory {\n address public immutable api3Token;\n\n address public immutable irrevocableVestingImplementation;\n\n constructor(address _api3Token) {\n api3Token = _api3Token;\n irrevocableVestingImplementation = address(\n new IrrevocableVesting(_api3Token)\n );\n }\n\n function deployIrrevocableVestingWithoutTransferringTokens(\n address beneficiary,\n uint32 startTimestamp,\n uint32 endTimestamp,\n uint192 amount\n ) external returns (address irrevocableVesting) {\n irrevocableVesting = Clones.clone(irrevocableVestingImplementation);\n IIrrevocableVesting(irrevocableVesting).initialize(\n beneficiary,\n startTimestamp,\n endTimestamp,\n amount\n );\n }\n}\n" + }, + "contracts/mock/MockApi3Token.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract MockApi3Token is ERC20 {\n constructor() ERC20(\"API3\", \"API3\") {\n _mint(msg.sender, 100000000 ether);\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 1000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +}