Transactions
Token Transfers
Internal Transactions
Coin Balance History
Code
Read Contract
Write Contract
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
This contract has been partially verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- Reservoir
- Optimization enabled
- true
- Compiler version
- v0.8.11+commit.d7f03943
- Optimization runs
- 200
- EVM Version
- london
- Verified at
- 2023-07-07T23:50:05.423623Z
src/Reservoir.sol
// SPDX-License-Identifier: BSD-3-Clause pragma solidity ^0.8.10; import "src/WETH.sol"; /** * @title Reservoir Contract * @notice Distributes a wcanto to a different contract at a fixed rate. * @dev This contract must be poked via the `drip()` function every so often. * @author Compound */ contract Reservoir { /// @notice The block number when the Reservoir started (immutable) uint public dripStart; /// @notice wcantos per block that to drip to target (immutable) uint public dripRate; /// @notice Reference to wcanto to drip (immutable) WETH public wcanto; //WCanto /// @notice Target to receive dripped wcantos (immutable) address public target; /// @notice Amount that has already been dripped uint public dripped; /** * @notice Constructs a Reservoir * @param dripRate_ Numer of wcantos per block to drip * @param wcanto_ The wcanto to drip * @param target_ The recipient of dripped wcantos */ constructor(uint dripRate_, WETH wcanto_, address target_) public { dripStart = block.number; dripRate = dripRate_; wcanto = wcanto_; target = target_; dripped = 0; } /** * @notice Drips the maximum amount of wcantos to match the drip rate since inception * @dev Note: this will only drip up to the amount of wcantos available. * @return The amount of wcantos dripped in this call */ function drip() public returns (uint) { // First, read storage into memory WETH wcanto_ = wcanto; uint reservoirBalance_ = wcanto_.balanceOf(address(this)); // TODO: Verify this is a static call uint dripRate_ = dripRate; uint dripStart_ = dripStart; uint dripped_ = dripped; address target_ = target; uint blockNumber_ = block.number; // Next, calculate intermediate values uint dripTotal_ = mul(dripRate_, blockNumber_ - dripStart_, "dripTotal overflow"); uint deltaDrip_ = sub(dripTotal_, dripped_, "deltaDrip underflow"); uint toDrip_ = min(reservoirBalance_, deltaDrip_); uint drippedNext_ = add(dripped_, toDrip_, "tautological"); // Finally, write new `dripped` value and transfer wcantos to target dripped = drippedNext_; wcanto_.transfer(target_, toDrip_); return toDrip_; } receive() external payable { WETH wcanto_ = wcanto; wcanto_.deposit{value: msg.value}(); // deposit what was sent to this contract and receive the requisite amount of wcanto } /* Internal helper functions for safe math */ function add(uint a, uint b, string memory errorMessage) internal pure returns (uint) { uint c; unchecked { c = a + b; } require(c >= a, errorMessage); return c; } function sub(uint a, uint b, string memory errorMessage) internal pure returns (uint) { require(b <= a, errorMessage); uint c = a - b; return c; } function mul(uint a, uint b, string memory errorMessage) internal pure returns (uint) { if (a == 0) { return 0; } uint c; unchecked { c = a * b; } require(c / a == b, errorMessage); return c; } function min(uint a, uint b) internal pure returns (uint) { if (a <= b) { return a; } else { return b; } } } import "./EIP20Interface.sol";
/src/WETH.sol
pragma solidity ^0.8.10; import "./EIP20Interface.sol"; contract WETH is EIP20Interface { string private _name; string private _symbol; uint8 private _decimals = 18; mapping (address => uint) public _balanceOf; mapping (address => mapping (address => uint)) public _allowance; constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } receive() external payable { deposit(); } function deposit() public payable { _balanceOf[msg.sender] += msg.value; emit Deposit(msg.sender, msg.value); } function withdraw(uint wamount) public { require(_balanceOf[msg.sender] >= wamount, "sender balance insufficient for withdrawal"); _balanceOf[msg.sender] -= wamount; payable(msg.sender).transfer(wamount); // rentrant attack must be less than 2300 gas emit Withdrawal(msg.sender, wamount); } function name() external view returns (string memory) { return _name; } function symbol() external view returns (string memory) { return _symbol; } function decimals() external view returns (uint8) { return _decimals; } function totalSupply() public view returns (uint) { return address(this).balance; } function balanceOf(address owner) external view returns(uint256) { return _balanceOf[owner]; } function approve(address spender, uint amount) public returns (bool) { _approve(msg.sender, spender, amount); emit Approval(msg.sender, spender, amount); return true; } function transfer(address dst, uint wad) public returns (bool) { return transferFrom(msg.sender, dst, wad); } function transferFrom(address src, address dst, uint wad) public returns (bool) { require(_balanceOf[src] >= wad, "WETH::transfeFrom: balance insufficient"); if (src != msg.sender && _allowance[src][msg.sender] != type(uint).max) { require(_allowance[src][msg.sender] >= wad, "WETH::transferFrom:allowance insufficient"); _allowance[src][msg.sender] -= wad; } _balanceOf[src] -= wad; _balanceOf[dst] += wad; emit Transfer(src, dst, wad); return true; } function _approve( address owner, address spender, uint256 amount ) internal { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowance[owner][spender] = amount; emit Approval(owner, spender, amount); } function allowance(address owner, address spender) external view returns (uint256) { return _allowance[owner][spender]; } event Deposit(address indexed dst, uint wad); event Withdrawal(address indexed src, uint wad); }
/src/EIP20Interface.sol
// SPDX-License-Identifier: BSD-3-Clause pragma solidity ^0.8.10; /** * @title ERC 20 Token Standard Interface * https://eips.ethereum.org/EIPS/eip-20 */ interface EIP20Interface { function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); /** * @notice Get the total number of tokens in circulation * @return The supply of tokens */ function totalSupply() external view returns (uint256); /** * @notice Gets the balance of the specified address * @param owner The address from which the balance will be retrieved * @return balance The balance */ function balanceOf(address owner) external view returns (uint256 balance); /** * @notice Transfer `amount` tokens from `msg.sender` to `dst` * @param dst The address of the destination account * @param amount The number of tokens to transfer * @return success Whether or not the transfer succeeded */ function transfer(address dst, uint256 amount) external returns (bool success); /** * @notice Transfer `amount` tokens from `src` to `dst` * @param src The address of the source account * @param dst The address of the destination account * @param amount The number of tokens to transfer * @return success Whether or not the transfer succeeded */ function transferFrom(address src, address dst, uint256 amount) external returns (bool success); /** * @notice Approve `spender` to transfer up to `amount` from `src` * @dev This will overwrite the approval amount for `spender` * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve) * @param spender The address of the account which may transfer tokens * @param amount The number of tokens that are approved (-1 means infinite) * @return success Whether or not the approval succeeded */ function approve(address spender, uint256 amount) external returns (bool success); /** * @notice Get the current allowance from `owner` for `spender` * @param owner The address of the account which owns the tokens to be spent * @param spender The address of the account which may transfer tokens * @return remaining The number of tokens allowed to be spent (-1 means infinite) */ function allowance(address owner, address spender) external view returns (uint256 remaining); event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); }
Compiler Settings
{"remappings":[],"optimizer":{"runs":200,"enabled":true},"metadata":{"useLiteralContent":true,"bytecodeHash":"ipfs"},"libraries":{"::__CACHE_BREAKER__":"0x0000000000000031363630313837333733303434"},"evmVersion":"london","compilationTarget":{"src/Reservoir.sol":"Reservoir"}}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"dripRate_","internalType":"uint256"},{"type":"address","name":"wcanto_","internalType":"contract WETH"},{"type":"address","name":"target_","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"drip","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"dripRate","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"dripStart","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"dripped","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"target","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract WETH"}],"name":"wcanto","inputs":[]},{"type":"receive","stateMutability":"payable"}]
Contract Creation Code
0x608060405234801561001057600080fd5b5060405161061738038061061783398101604081905261002f91610087565b436000908155600193909355600280546001600160a01b039384166001600160a01b031991821617909155600380549290931691161790556004556100ca565b6001600160a01b038116811461008457600080fd5b50565b60008060006060848603121561009c57600080fd5b8351925060208401516100ae8161006f565b60408501519092506100bf8161006f565b809150509250925092565b61053e806100d96000396000f3fe6080604052600436106100595760003560e01c80637aa497d9146100c957806388a91a8a1461010657806395f632b31461012a5780639f678cca14610140578063d326159214610155578063d4b839921461016b57600080fd5b366100c45760025460408051630d0e30db60e41b815290516001600160a01b0390921691829163d0e30db091349160048082019260009290919082900301818588803b1580156100a857600080fd5b505af11580156100bc573d6000803e3d6000fd5b505050505050005b600080fd5b3480156100d557600080fd5b506002546100e9906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561011257600080fd5b5061011c60005481565b6040519081526020016100fd565b34801561013657600080fd5b5061011c60045481565b34801561014c57600080fd5b5061011c61018b565b34801561016157600080fd5b5061011c60015481565b34801561017757600080fd5b506003546100e9906001600160a01b031681565b6002546040516370a0823160e01b81523060048201526000916001600160a01b031690829082906370a0823190602401602060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610431565b6001546000805460045460035494955092939092916001600160a01b0390911690439061025d8661022d878561044a565b6040518060400160405280601281526020017164726970546f74616c206f766572666c6f7760701b815250610366565b9050600061029782866040518060400160405280601381526020017264656c74614472697020756e646572666c6f7760681b8152506103b7565b905060006102a589836103f1565b905060006102d887836040518060400160405280600c81526020016b1d185d5d1bdb1bd9da58d85b60a21b81525061040a565b600481815560405163a9059cbb60e01b81526001600160a01b0389811692820192909252602481018590529192508c169063a9059cbb906044016020604051808303816000875af1158015610331573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610355919061046f565b50909b9a5050505050505050505050565b600083610375575060006103b0565b838302836103838683610491565b1483906103ac5760405162461bcd60e51b81526004016103a391906104b3565b60405180910390fd5b5090505b9392505050565b600081848411156103db5760405162461bcd60e51b81526004016103a391906104b3565b5060006103e8848661044a565b95945050505050565b6000818311610401575081610404565b50805b92915050565b600083830182858210156103ac5760405162461bcd60e51b81526004016103a391906104b3565b60006020828403121561044357600080fd5b5051919050565b60008282101561046a57634e487b7160e01b600052601160045260246000fd5b500390565b60006020828403121561048157600080fd5b815180151581146103b057600080fd5b6000826104ae57634e487b7160e01b600052601260045260246000fd5b500490565b600060208083528351808285015260005b818110156104e0578581018301518582016040015282016104c4565b818111156104f2576000604083870101525b50601f01601f191692909201604001939250505056fea264697066735822122064af5e2957be371553ae5df4f89b4643c78fadba2ced0d636ae01e0bf0b4d27264736f6c634300080b0033000000000000000000000000000000000000000000000007cb4fa4aeeafba800000000000000000000000000826551890dc65655a0aceca109ab11abdbd7a07b0000000000000000000000005e23dc409fc2f832f83cec191e245a191a4bcc5c
Deployed ByteCode
0x6080604052600436106100595760003560e01c80637aa497d9146100c957806388a91a8a1461010657806395f632b31461012a5780639f678cca14610140578063d326159214610155578063d4b839921461016b57600080fd5b366100c45760025460408051630d0e30db60e41b815290516001600160a01b0390921691829163d0e30db091349160048082019260009290919082900301818588803b1580156100a857600080fd5b505af11580156100bc573d6000803e3d6000fd5b505050505050005b600080fd5b3480156100d557600080fd5b506002546100e9906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561011257600080fd5b5061011c60005481565b6040519081526020016100fd565b34801561013657600080fd5b5061011c60045481565b34801561014c57600080fd5b5061011c61018b565b34801561016157600080fd5b5061011c60015481565b34801561017757600080fd5b506003546100e9906001600160a01b031681565b6002546040516370a0823160e01b81523060048201526000916001600160a01b031690829082906370a0823190602401602060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190610431565b6001546000805460045460035494955092939092916001600160a01b0390911690439061025d8661022d878561044a565b6040518060400160405280601281526020017164726970546f74616c206f766572666c6f7760701b815250610366565b9050600061029782866040518060400160405280601381526020017264656c74614472697020756e646572666c6f7760681b8152506103b7565b905060006102a589836103f1565b905060006102d887836040518060400160405280600c81526020016b1d185d5d1bdb1bd9da58d85b60a21b81525061040a565b600481815560405163a9059cbb60e01b81526001600160a01b0389811692820192909252602481018590529192508c169063a9059cbb906044016020604051808303816000875af1158015610331573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610355919061046f565b50909b9a5050505050505050505050565b600083610375575060006103b0565b838302836103838683610491565b1483906103ac5760405162461bcd60e51b81526004016103a391906104b3565b60405180910390fd5b5090505b9392505050565b600081848411156103db5760405162461bcd60e51b81526004016103a391906104b3565b5060006103e8848661044a565b95945050505050565b6000818311610401575081610404565b50805b92915050565b600083830182858210156103ac5760405162461bcd60e51b81526004016103a391906104b3565b60006020828403121561044357600080fd5b5051919050565b60008282101561046a57634e487b7160e01b600052601160045260246000fd5b500390565b60006020828403121561048157600080fd5b815180151581146103b057600080fd5b6000826104ae57634e487b7160e01b600052601260045260246000fd5b500490565b600060208083528351808285015260005b818110156104e0578581018301518582016040015282016104c4565b818111156104f2576000604083870101525b50601f01601f191692909201604001939250505056fea264697066735822122064af5e2957be371553ae5df4f89b4643c78fadba2ced0d636ae01e0bf0b4d27264736f6c634300080b0033
External libraries
::__CACHE_BREAKER__ : 0x0000000000000031363630313837333733303434