Address Contract Partially Verified
Address
0xc92FAb4De20E5C2A3Ca5BA7DB4dd81480Ad1Ff04
Balance
0 ETH
Nonce
2
Code Size
5956 bytes
Creator
0xE2388f22...a510 at tx 0xce810412...86f631
Indexed Transactions
0
Contract Bytecode
5956 bytes
0x60806040523480156200001157600080fd5b50600436106200016b5760003560e01c806367fc6dea11620000d5578063b38c43e31162000087578063b38c43e31462000279578063b86677fe1462000290578063b888c479146200029a578063c5fa55a514620002a4578063cf4f363014620002bb578063da8be86414620002d2576200016b565b806367fc6dea146200023057806378e97925146200023a57806380d04de814620002445780639e88d77e146200024e578063acc4bd081462000265578063ae951b2e146200026f576200016b565b806318369a2a116200012f57806318369a2a14620001f457806328b5030b14620001fe57806338af3eed1462000208578063427db38014620002125780634929e162146200021c578063626be5671462000226576200016b565b8062d89b331462000170578063026e402b14620001925780630357371d14620001ab5780630f45cc8114620001c25780630fb5a6b414620001db575b600080fd5b6200017a620002e9565b60405162000189919062000e18565b60405180910390f35b620001a9620001a336600462000d69565b620002f2565b005b620001a9620001bc36600462000d69565b62000503565b620001cc620005f0565b60405162000189919062000dd1565b620001e5620005ff565b604051620001899190620010c3565b620001e562000605565b620001e56200060b565b620001cc6200066b565b620001cc6200067a565b620001a962000689565b620001e5620006fc565b620001e562000721565b620001e56200075b565b620001e562000761565b620001e56200025f36600462000d4b565b62000767565b620001e562000779565b6200017a6200078e565b620001a96200028a36600462000d4b565b620007a0565b620001cc62000836565b620001e562000845565b620001a9620002b536600462000d4b565b62000865565b620001cc620002cc36600462000d4b565b620008dc565b620001e5620002e336600462000d4b565b620008f7565b60005415155b90565b6003546001600160a01b03163314620003285760405162461bcd60e51b81526004016200031f9062000eff565b60405180910390fd5b6200033262000a56565b811115620003545760405162461bcd60e51b81526004016200031f9062000fe2565b6001600160a01b0382811660009081526007602052604090205416156200039557620003926200038483620008f7565b829063ffffffff62000add16565b90505b6009546040516001600160a01b039091169060009084908390620003b99062000d25565b620003c692919062000de5565b604051809103906000f080158015620003e3573d6000803e3d6000fd5b506001600160a01b03858116600090815260076020908152604080832080546001600160a01b031916948616949094179093556008905220849055600a5490915062000430908462000add565b600a5560405163a9059cbb60e01b81526001600160a01b0383169063a9059cbb9062000463908490879060040162000dff565b602060405180830381600087803b1580156200047e57600080fd5b505af115801562000493573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004b9919062000d96565b50836001600160a01b03167fb0d234274aef7a61aa5a2eb44c23881ebf46a068cccbd413c978bcbd555fe17f84604051620004f59190620010c3565b60405180910390a250505050565b6003546001600160a01b03163314620005305760405162461bcd60e51b81526004016200031f9062000eff565b6006546200053d620006fc565b1115620005815760006200056460065462000557620006fc565b9063ffffffff62000b0e16565b6005549091506200057c908263ffffffff62000add16565b600555505b80620005a15760405162461bcd60e51b81526004016200031f906200107d565b6000620005ad6200060b565b905080821115620005d25760405162461bcd60e51b81526004016200031f9062000e79565b620005de838362000b52565b50620005e9620006fc565b6006555050565b6002546001600160a01b031681565b60015481565b60055481565b6000806200061862000721565b60015460055491925090600090829062000639908563ffffffff62000c2c16565b816200064157fe5b0490506000620006626200065462000845565b839063ffffffff62000b0e16565b94505050505090565b6003546001600160a01b031681565b6004546001600160a01b031681565b620006943362000c6c565b6009546040516317066a5760e21b81526001600160a01b0390911690635c19a95c90620006c690339060040162000dd1565b600060405180830381600087803b158015620006e157600080fd5b505af1158015620006f6573d6000803e3d6000fd5b50505050565b60006200071c600a546200070f62000a56565b9063ffffffff62000add16565b905090565b60006200072d620002e9565b6200073b57506000620002ef565b600154600054420381811162000752578062000754565b815b9250505090565b60005481565b600a5481565b60086020526000908152604090205481565b60006200078562000721565b60015403905090565b60006200079a62000779565b15905090565b6003546001600160a01b03163314620007cd5760405162461bcd60e51b81526004016200031f9062000eff565b600654620007da620006fc565b111562000811576000620007f460065462000557620006fc565b6005549091506200080c908263ffffffff62000add16565b600555505b6200082681620008206200060b565b62000b52565b62000830620006fc565b60065550565b6009546001600160a01b031681565b60006200071c62000855620006fc565b6005549063ffffffff62000b0e16565b6003546001600160a01b03163314620008925760405162461bcd60e51b81526004016200031f9062000eff565b600480546001600160a01b0319166001600160a01b0383169081179091556040517f636f16dafcc1e5b7ae44b2a7fd661757f160672716bb47a02c7d3f5108be49a090600090a250565b6007602052600090815260409020546001600160a01b031681565b6003546000906001600160a01b03163314620009275760405162461bcd60e51b81526004016200031f9062000eff565b6001600160a01b038083166000908152600760205260409020541680620009625760405162461bcd60e51b81526004016200031f9062000f4f565b806001600160a01b0316633ccfd60b6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156200099e57600080fd5b505af1158015620009b3573d6000803e3d6000fd5b505050506001600160a01b038316600090815260086020526040902054600a54620009df908262000b0e565b600a556001600160a01b038416600081815260076020908152604080832080546001600160a01b0319169055600890915280822091909155517f17659a1d1f57d2e58b7063ee8b518b50d00bf3e5c0d8224b68ba865e4725a0b49062000a47908490620010c3565b60405180910390a29392505050565b6009546040516370a0823160e01b81526000916001600160a01b0316906370a082319062000a8990309060040162000dd1565b60206040518083038186803b15801562000aa257600080fd5b505afa15801562000ab7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200071c919062000db8565b60008282018381101562000b055760405162461bcd60e51b81526004016200031f9062000ec8565b90505b92915050565b600062000b0583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525062000cf6565b60025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb9062000b86908590859060040162000dff565b602060405180830381600087803b15801562000ba157600080fd5b505af115801562000bb6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000bdc919062000d96565b506003546040516001600160a01b038085169216907fcb54aad3bd772fcfe1bc124e01bd1a91a91c9d80126d8b3014c4d9e687d5ca489062000c20908590620010c3565b60405180910390a35050565b60008262000c3d5750600062000b08565b8282028284828162000c4b57fe5b041462000b055760405162461bcd60e51b81526004016200031f9062000fa1565b6004546001600160a01b0382811691161462000c9c5760405162461bcd60e51b81526004016200031f9062001027565b600380546001600160a01b0319166001600160a01b0383169081179091556040517fe356863d8c81d46ff30d41a6332e1d04d2fb6c0f043fa6554e3d1e1deae95a8a90600090a250600480546001600160a01b0319169055565b6000818484111562000d1d5760405162461bcd60e51b81526004016200031f919062000e23565b505050900390565b61064280620010cd83390190565b80356001600160a01b038116811462000b0857600080fd5b60006020828403121562000d5d578081fd5b62000b05838362000d33565b6000806040838503121562000d7c578081fd5b62000d88848462000d33565b946020939093013593505050565b60006020828403121562000da8578081fd5b8151801515811462000b05578182fd5b60006020828403121562000dca578081fd5b5051919050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b6000602080835283518082850152825b8181101562000e515785810183015185820160400152820162000e33565b8181111562000e635783604083870101525b50601f01601f1916929092016040019392505050565b6020808252602f908201527f4c696e656172546f6b656e54696d656c6f636b3a206e6f7420656e6f7567682060408201526e72656c656173656420746f6b656e7360881b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526030908201527f4c696e656172546f6b656e54696d656c6f636b3a2043616c6c6572206973206e60408201526f6f7420612062656e656669636961727960801b606082015260800190565b60208082526032908201527f54696d656c6f636b656444656c656761746f723a2044656c656761746520636f6040820152711b9d1c9858dd081b9bdb995e1a5cdd195b9d60721b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526025908201527f54696d656c6f636b656444656c656761746f723a204e6f7420656e6f75676820604082015264547269626560d81b606082015260800190565b60208082526036908201527f4c696e656172546f6b656e54696d656c6f636b3a2043616c6c6572206973206e6040820152756f742070656e64696e672062656e656669636961727960501b606082015260800190565b60208082526026908201527f4c696e656172546f6b656e54696d656c6f636b3a206e6f20616d6f756e742064604082015265195cda5c995960d21b606082015260800190565b9081526020019056fe608060405234801561001057600080fd5b5060405161064238038061064283398101604081905261002f9161010e565b60006100426001600160e01b0361010a16565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350600180546001600160a01b0319166001600160a01b0383811691909117918290556040516317066a5760e21b8152911690635c19a95c906100d1908590600401610147565b600060405180830381600087803b1580156100eb57600080fd5b505af11580156100ff573d6000803e3d6000fd5b505050505050610173565b3390565b60008060408385031215610120578182fd5b825161012b8161015b565b602084015190925061013c8161015b565b809150509250929050565b6001600160a01b0391909116815260200190565b6001600160a01b038116811461017057600080fd5b50565b6104c0806101826000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80633ccfd60b1461005c578063715018a6146100665780638da5cb5b1461006e578063b86677fe1461008c578063f2fde38b14610094575b600080fd5b6100646100a7565b005b610064610211565b61007661029a565b60405161008391906103e2565b60405180910390f35b6100766102a9565b6100646100a236600461037c565b6102b8565b6100af610378565b6001600160a01b03166100c061029a565b6001600160a01b0316146100ef5760405162461bcd60e51b81526004016100e690610455565b60405180910390fd5b6001546040516370a0823160e01b81526001600160a01b039091169060009082906370a08231906101249030906004016103e2565b60206040518083038186803b15801561013c57600080fd5b505afa158015610150573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061017491906103ca565b9050816001600160a01b031663a9059cbb61018d61029a565b836040518363ffffffff1660e01b81526004016101ab9291906103f6565b602060405180830381600087803b1580156101c557600080fd5b505af11580156101d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fd91906103aa565b5061020661029a565b6001600160a01b0316ff5b610219610378565b6001600160a01b031661022a61029a565b6001600160a01b0316146102505760405162461bcd60e51b81526004016100e690610455565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b031690565b6001546001600160a01b031681565b6102c0610378565b6001600160a01b03166102d161029a565b6001600160a01b0316146102f75760405162461bcd60e51b81526004016100e690610455565b6001600160a01b03811661031d5760405162461bcd60e51b81526004016100e69061040f565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b3390565b60006020828403121561038d578081fd5b81356001600160a01b03811681146103a3578182fd5b9392505050565b6000602082840312156103bb578081fd5b815180151581146103a3578182fd5b6000602082840312156103db578081fd5b5051919050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260408201526060019056fea2646970667358221220386ea63ca2f318b02deda68ffd17822438160431e507fb700f13923eab8f078f64736f6c63430006060033a264697066735822122006f2ef7ff1d6d1333faa5b157baa1f2fe6aba4e80ba5831f4df08ace524cef5164736f6c63430006060033
Verified Source Code Partial Match
Compiler: v0.6.6+commit.6c089d02
EVM: istanbul
Optimization: Yes (200 runs)
IFei.sol 56 lines
pragma solidity ^0.6.2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/// @title FEI stablecoin interface
/// @author Fei Protocol
interface IFei is IERC20 {
// ----------- Events -----------
event Minting(
address indexed _to,
address indexed _minter,
uint256 _amount
);
event Burning(
address indexed _to,
address indexed _burner,
uint256 _amount
);
event IncentiveContractUpdate(
address indexed _incentivized,
address indexed _incentiveContract
);
// ----------- State changing api -----------
function burn(uint256 amount) external;
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
// ----------- Burner only state changing api -----------
function burnFrom(address account, uint256 amount) external;
// ----------- Minter only state changing api -----------
function mint(address account, uint256 amount) external;
// ----------- Governor only state changing api -----------
function setIncentiveContract(address account, address incentive) external;
// ----------- Getters -----------
function incentiveContract(address account) external view returns (address);
}
Timed.sol 76 lines
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/utils/SafeCast.sol";
/// @title an abstract contract for timed events
/// @author Fei Protocol
abstract contract Timed {
using SafeCast for uint256;
/// @notice the start timestamp of the timed period
uint256 public startTime;
/// @notice the duration of the timed period
uint256 public duration;
event DurationUpdate(uint256 _duration);
event TimerReset(uint256 _startTime);
constructor(uint256 _duration) public {
_setDuration(_duration);
}
modifier duringTime() {
require(isTimeStarted(), "Timed: time not started");
require(!isTimeEnded(), "Timed: time ended");
_;
}
modifier afterTime() {
require(isTimeEnded(), "Timed: time not ended");
_;
}
/// @notice return true if time period has ended
function isTimeEnded() public view returns (bool) {
return remainingTime() == 0;
}
/// @notice number of seconds remaining until time is up
/// @return remaining
function remainingTime() public view returns (uint256) {
return duration - timeSinceStart(); // duration always >= timeSinceStart which is on [0,d]
}
/// @notice number of seconds since contract was initialized
/// @return timestamp
/// @dev will be less than or equal to duration
function timeSinceStart() public view returns (uint256) {
if (!isTimeStarted()) {
return 0; // uninitialized
}
uint256 _duration = duration;
// solhint-disable-next-line not-rely-on-time
uint256 timePassed = block.timestamp - startTime; // block timestamp always >= startTime
return timePassed > _duration ? _duration : timePassed;
}
function isTimeStarted() public view returns (bool) {
return startTime != 0;
}
function _initTimed() internal {
// solhint-disable-next-line not-rely-on-time
startTime = block.timestamp;
// solhint-disable-next-line not-rely-on-time
emit TimerReset(block.timestamp);
}
function _setDuration(uint _duration) internal {
duration = _duration;
emit DurationUpdate(_duration);
}
}
SafeMathCopy.sol 159 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.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 SafeMathCopy { // To avoid namespace collision between openzeppelin safemath and uniswap safemath
/**
* @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) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* 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);
uint256 c = a - b;
return c;
}
/**
* @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) {
// 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 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts 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) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message 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, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts 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) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message 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, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
TimelockedDelegator.sol 134 lines
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/access/Ownable.sol";
import "./ITimelockedDelegator.sol";
import "../utils/LinearTokenTimelock.sol";
/// @title a proxy delegate contract for TRIBE
/// @author Fei Protocol
contract Delegatee is Ownable {
ITribe public tribe;
/// @notice Delegatee constructor
/// @param _delegatee the address to delegate TRIBE to
/// @param _tribe the TRIBE token address
constructor(address _delegatee, address _tribe) public {
tribe = ITribe(_tribe);
tribe.delegate(_delegatee);
}
/// @notice send TRIBE back to timelock and selfdestruct
function withdraw() public onlyOwner {
ITribe _tribe = tribe;
uint256 balance = _tribe.balanceOf(address(this));
_tribe.transfer(owner(), balance);
selfdestruct(payable(owner()));
}
}
/// @title a timelock for TRIBE allowing for sub-delegation
/// @author Fei Protocol
/// @notice allows the timelocked TRIBE to be delegated by the beneficiary while locked
contract TimelockedDelegator is ITimelockedDelegator, LinearTokenTimelock {
/// @notice associated delegate proxy contract for a delegatee
mapping(address => address) public override delegateContract;
/// @notice associated delegated amount of TRIBE for a delegatee
/// @dev Using as source of truth to prevent accounting errors by transferring to Delegate contracts
mapping(address => uint256) public override delegateAmount;
/// @notice the TRIBE token contract
ITribe public override tribe;
/// @notice the total delegated amount of TRIBE
uint256 public override totalDelegated;
/// @notice Delegatee constructor
/// @param _tribe the TRIBE token address
/// @param _beneficiary default delegate, admin, and timelock beneficiary
/// @param _duration duration of the token timelock window
constructor(
address _tribe,
address _beneficiary,
uint256 _duration
) public LinearTokenTimelock(_beneficiary, _duration, _tribe) {
tribe = ITribe(_tribe);
tribe.delegate(_beneficiary);
}
/// @notice delegate locked TRIBE to a delegatee
/// @param delegatee the target address to delegate to
/// @param amount the amount of TRIBE to delegate. Will increment existing delegated TRIBE
function delegate(address delegatee, uint256 amount)
public
override
onlyBeneficiary
{
require(
amount <= _tribeBalance(),
"TimelockedDelegator: Not enough Tribe"
);
// withdraw and include an existing delegation
if (delegateContract[delegatee] != address(0)) {
amount = amount.add(undelegate(delegatee));
}
ITribe _tribe = tribe;
address _delegateContract =
address(new Delegatee(delegatee, address(_tribe)));
delegateContract[delegatee] = _delegateContract;
delegateAmount[delegatee] = amount;
totalDelegated = totalDelegated.add(amount);
_tribe.transfer(_delegateContract, amount);
emit Delegate(delegatee, amount);
}
/// @notice return delegated TRIBE to the timelock
/// @param delegatee the target address to undelegate from
/// @return the amount of TRIBE returned
function undelegate(address delegatee)
public
override
onlyBeneficiary
returns (uint256)
{
address _delegateContract = delegateContract[delegatee];
require(
_delegateContract != address(0),
"TimelockedDelegator: Delegate contract nonexistent"
);
Delegatee(_delegateContract).withdraw();
uint256 amount = delegateAmount[delegatee];
totalDelegated = totalDelegated.sub(amount);
delegateContract[delegatee] = address(0);
delegateAmount[delegatee] = 0;
emit Undelegate(delegatee, amount);
return amount;
}
/// @notice calculate total TRIBE held plus delegated
/// @dev used by LinearTokenTimelock to determine the released amount
function totalToken() public view override returns (uint256) {
return _tribeBalance().add(totalDelegated);
}
/// @notice accept beneficiary role over timelocked TRIBE. Delegates all held (non-subdelegated) tribe to beneficiary
function acceptBeneficiary() public override {
_setBeneficiary(msg.sender);
tribe.delegate(msg.sender);
}
function _tribeBalance() internal view returns (uint256) {
return tribe.balanceOf(address(this));
}
}
ITimelockedDelegator.sol 38 lines
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../token/IFei.sol";
interface ITribe is IERC20 {
function delegate(address delegatee) external;
}
/// @title TimelockedDelegator interface
/// @author Fei Protocol
interface ITimelockedDelegator {
// ----------- Events -----------
event Delegate(address indexed _delegatee, uint256 _amount);
event Undelegate(address indexed _delegatee, uint256 _amount);
// ----------- Beneficiary only state changing api -----------
function delegate(address delegatee, uint256 amount) external;
function undelegate(address delegatee) external returns (uint256);
// ----------- Getters -----------
function delegateContract(address delegatee)
external
view
returns (address);
function delegateAmount(address delegatee) external view returns (uint256);
function totalDelegated() external view returns (uint256);
function tribe() external view returns (ITribe);
}
LinearTokenTimelock.sol 130 lines
pragma solidity ^0.6.0;
// Inspired by OpenZeppelin TokenTimelock contract
// Reference: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/TokenTimelock.sol
import "./Timed.sol";
import "./ILinearTokenTimelock.sol";
import "../external/SafeMathCopy.sol";
contract LinearTokenTimelock is ILinearTokenTimelock, Timed {
using SafeMathCopy for uint256;
/// @notice ERC20 basic token contract being held in timelock
IERC20 public override lockedToken;
/// @notice beneficiary of tokens after they are released
address public override beneficiary;
/// @notice pending beneficiary appointed by current beneficiary
address public override pendingBeneficiary;
/// @notice initial balance of lockedToken
uint256 public override initialBalance;
uint256 internal lastBalance;
constructor(
address _beneficiary,
uint256 _duration,
address _lockedToken
) public Timed(_duration) {
require(_duration != 0, "LinearTokenTimelock: duration is 0");
require(
_beneficiary != address(0),
"LinearTokenTimelock: Beneficiary must not be 0 address"
);
beneficiary = _beneficiary;
_initTimed();
_setLockedToken(_lockedToken);
}
// Prevents incoming LP tokens from messing up calculations
modifier balanceCheck() {
if (totalToken() > lastBalance) {
uint256 delta = totalToken().sub(lastBalance);
initialBalance = initialBalance.add(delta);
}
_;
lastBalance = totalToken();
}
modifier onlyBeneficiary() {
require(
msg.sender == beneficiary,
"LinearTokenTimelock: Caller is not a beneficiary"
);
_;
}
/// @notice releases `amount` unlocked tokens to address `to`
function release(address to, uint256 amount) external override onlyBeneficiary balanceCheck {
require(amount != 0, "LinearTokenTimelock: no amount desired");
uint256 available = availableForRelease();
require(amount <= available, "LinearTokenTimelock: not enough released tokens");
_release(to, amount);
}
/// @notice releases maximum unlocked tokens to address `to`
function releaseMax(address to) external override onlyBeneficiary balanceCheck {
_release(to, availableForRelease());
}
/// @notice the total amount of tokens held by timelock
function totalToken() public view override virtual returns (uint256) {
return lockedToken.balanceOf(address(this));
}
/// @notice amount of tokens released to beneficiary
function alreadyReleasedAmount() public view override returns (uint256) {
return initialBalance.sub(totalToken());
}
/// @notice amount of held tokens unlocked and available for release
function availableForRelease() public view override returns (uint256) {
uint256 elapsed = timeSinceStart();
uint256 _duration = duration;
uint256 totalAvailable = initialBalance.mul(elapsed) / _duration;
uint256 netAvailable = totalAvailable.sub(alreadyReleasedAmount());
return netAvailable;
}
/// @notice current beneficiary can appoint new beneficiary, which must be accepted
function setPendingBeneficiary(address _pendingBeneficiary)
public
override
onlyBeneficiary
{
pendingBeneficiary = _pendingBeneficiary;
emit PendingBeneficiaryUpdate(_pendingBeneficiary);
}
/// @notice pending beneficiary accepts new beneficiary
function acceptBeneficiary() public override virtual {
_setBeneficiary(msg.sender);
}
function _setBeneficiary(address newBeneficiary) internal {
require(
newBeneficiary == pendingBeneficiary,
"LinearTokenTimelock: Caller is not pending beneficiary"
);
beneficiary = newBeneficiary;
emit BeneficiaryUpdate(newBeneficiary);
pendingBeneficiary = address(0);
}
function _setLockedToken(address tokenAddress) internal {
lockedToken = IERC20(tokenAddress);
}
function _release(address to, uint256 amount) internal {
lockedToken.transfer(to, amount);
emit Release(beneficiary, to, amount);
}
}
Context.sol 24 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
ILinearTokenTimelock.sol 40 lines
pragma solidity ^0.6.2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/// @title LinearTokenTimelock interface
/// @author Fei Protocol
interface ILinearTokenTimelock {
// ----------- Events -----------
event Release(address indexed _beneficiary, address indexed _recipient, uint256 _amount);
event BeneficiaryUpdate(address indexed _beneficiary);
event PendingBeneficiaryUpdate(address indexed _pendingBeneficiary);
// ----------- State changing api -----------
function release(address to, uint amount) external;
function releaseMax(address to) external;
function setPendingBeneficiary(address _pendingBeneficiary) external;
function acceptBeneficiary() external;
// ----------- Getters -----------
function lockedToken() external view returns (IERC20);
function beneficiary() external view returns (address);
function pendingBeneficiary() external view returns (address);
function initialBalance() external view returns (uint256);
function availableForRelease() external view returns (uint256);
function totalToken() external view returns(uint256);
function alreadyReleasedAmount() external view returns (uint256);
}
Ownable.sol 68 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
SafeCast.sol 211 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` 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 SafeCast {
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits");
return uint128(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits");
return uint64(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits");
return uint32(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits");
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*/
function toUint8(uint256 value) internal pure returns (uint8) {
require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits");
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v3.1._
*/
function toInt128(int256 value) internal pure returns (int128) {
require(value >= -2**127 && value < 2**127, "SafeCast: value doesn\'t fit in 128 bits");
return int128(value);
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v3.1._
*/
function toInt64(int256 value) internal pure returns (int64) {
require(value >= -2**63 && value < 2**63, "SafeCast: value doesn\'t fit in 64 bits");
return int64(value);
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v3.1._
*/
function toInt32(int256 value) internal pure returns (int32) {
require(value >= -2**31 && value < 2**31, "SafeCast: value doesn\'t fit in 32 bits");
return int32(value);
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v3.1._
*/
function toInt16(int256 value) internal pure returns (int16) {
require(value >= -2**15 && value < 2**15, "SafeCast: value doesn\'t fit in 16 bits");
return int16(value);
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*
* _Available since v3.1._
*/
function toInt8(int256 value) internal pure returns (int8) {
require(value >= -2**7 && value < 2**7, "SafeCast: value doesn\'t fit in 8 bits");
return int8(value);
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
require(value < 2**255, "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}
IERC20.sol 77 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
Read Contract
alreadyReleasedAmount 0xb888c479 → uint256
availableForRelease 0x28b5030b → uint256
beneficiary 0x38af3eed → address
delegateAmount 0x9e88d77e → uint256
delegateContract 0xcf4f3630 → address
duration 0x0fb5a6b4 → uint256
initialBalance 0x18369a2a → uint256
isTimeEnded 0xae951b2e → bool
isTimeStarted 0x00d89b33 → bool
lockedToken 0x0f45cc81 → address
pendingBeneficiary 0x427db380 → address
remainingTime 0xacc4bd08 → uint256
startTime 0x78e97925 → uint256
timeSinceStart 0x67fc6dea → uint256
totalDelegated 0x80d04de8 → uint256
totalToken 0x626be567 → uint256
tribe 0xb86677fe → address
Write Contract 6 functions
These functions modify contract state and require a wallet transaction to execute.
acceptBeneficiary 0x4929e162
No parameters
delegate 0x026e402b
address delegatee
uint256 amount
release 0x0357371d
address to
uint256 amount
releaseMax 0xb38c43e3
address to
setPendingBeneficiary 0xc5fa55a5
address _pendingBeneficiary
undelegate 0xda8be864
address delegatee
returns: uint256
Recent Transactions
No transactions found for this address