Contract Name:
SHRIMPDelegate
Contract Source Code:
File 1 of 1 : SHRIMPDelegate
/**
*Submitted for verification at Etherscan.io on 2020-08-11
*/
pragma solidity 0.5.17;
library 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;
}
}
contract YAMTokenStorage {
using SafeMath for uint256;
/**
* @dev Guard variable for re-entrancy checks. Not currently used
*/
bool internal _notEntered;
/**
* @notice EIP-20 token name for this token
*/
string public name;
/**
* @notice EIP-20 token symbol for this token
*/
string public symbol;
/**
* @notice EIP-20 token decimals for this token
*/
uint8 public decimals;
/**
* @notice Governor for this contract
*/
address public gov;
/**
* @notice Pending governance for this contract
*/
address public pendingGov;
/**
* @notice Approved rebaser for this contract
*/
address public rebaser;
/**
* @notice Reserve address of YAM protocol
*/
address public incentivizer;
/**
* @notice Total supply of YAMs
*/
uint256 public totalSupply;
/**
* @notice Internal decimals used to handle scaling factor
*/
uint256 public constant internalDecimals = 10**24;
/**
* @notice Used for percentage maths
*/
uint256 public constant BASE = 10**18;
/**
* @notice Scaling factor that adjusts everyone's balances
*/
uint256 public yamsScalingFactor;
mapping (address => uint256) internal _yamBalances;
mapping (address => mapping (address => uint256)) internal _allowedFragments;
uint256 public initSupply;
}
contract YAMGovernanceStorage {
/// @notice A record of each accounts delegate
mapping (address => address) internal _delegates;
/// @notice A checkpoint for marking number of votes from a given block
struct Checkpoint {
uint32 fromBlock;
uint256 votes;
}
/// @notice A record of votes checkpoints for each account, by index
mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;
/// @notice The number of checkpoints for each account
mapping (address => uint32) public numCheckpoints;
/// @notice The EIP-712 typehash for the contract's domain
bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");
/// @notice The EIP-712 typehash for the delegation struct used by the contract
bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");
/// @notice A record of states for signing / validating signatures
mapping (address => uint) public nonces;
}
contract YAMTokenInterface is YAMTokenStorage, YAMGovernanceStorage {
/// @notice An event thats emitted when an account changes its delegate
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
/// @notice An event thats emitted when a delegate account's vote balance changes
event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);
/**
* @notice Event emitted when tokens are rebased
*/
event Rebase(uint256 epoch, uint256 prevYamsScalingFactor, uint256 newYamsScalingFactor);
/*** Gov Events ***/
/**
* @notice Event emitted when pendingGov is changed
*/
event NewPendingGov(address oldPendingGov, address newPendingGov);
/**
* @notice Event emitted when gov is changed
*/
event NewGov(address oldGov, address newGov);
/**
* @notice Sets the rebaser contract
*/
event NewRebaser(address oldRebaser, address newRebaser);
/**
* @notice Sets the incentivizer contract
*/
event NewIncentivizer(address oldIncentivizer, address newIncentivizer);
/* - ERC20 Events - */
/**
* @notice EIP20 Transfer event
*/
event Transfer(address indexed from, address indexed to, uint amount);
/**
* @notice EIP20 Approval event
*/
event Approval(address indexed owner, address indexed spender, uint amount);
/* - Extra Events - */
/**
* @notice Tokens minted event
*/
event Mint(address to, uint256 amount);
// Public functions
function transfer(address to, uint256 value) external returns(bool);
function transferFrom(address from, address to, uint256 value) external returns(bool);
function balanceOf(address who) external view returns(uint256);
function balanceOfUnderlying(address who) external view returns(uint256);
function allowance(address owner_, address spender) external view returns(uint256);
function approve(address spender, uint256 value) external returns (bool);
function increaseAllowance(address spender, uint256 addedValue) external returns (bool);
function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);
function maxScalingFactor() external view returns (uint256);
/* - Governance Functions - */
function getPriorVotes(address account, uint blockNumber) external view returns (uint256);
function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) external;
function delegate(address delegatee) external;
function delegates(address delegator) external view returns (address);
function getCurrentVotes(address account) external view returns (uint256);
/* - Permissioned/Governance functions - */
function mint(address to, uint256 amount) external returns (bool);
function rebase(uint256 epoch, uint256 indexDelta, bool positive) external returns (uint256);
function _setRebaser(address rebaser_) external;
function _setIncentivizer(address incentivizer_) external;
function _setPendingGov(address pendingGov_) external;
function _acceptGov() external;
}
contract YAMGovernanceToken is YAMTokenInterface {
/// @notice An event thats emitted when an account changes its delegate
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
/// @notice An event thats emitted when a delegate account's vote balance changes
event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);
/**
* @notice Delegate votes from `msg.sender` to `delegatee`
* @param delegator The address to get delegatee for
*/
function delegates(address delegator)
external
view
returns (address)
{
return _delegates[delegator];
}
/**
* @notice Delegate votes from `msg.sender` to `delegatee`
* @param delegatee The address to delegate votes to
*/
function delegate(address delegatee) external {
return _delegate(msg.sender, delegatee);
}
/**
* @notice Delegates votes from signatory to `delegatee`
* @param delegatee The address to delegate votes to
* @param nonce The contract state required to match the signature
* @param expiry The time at which to expire the signature
* @param v The recovery byte of the signature
* @param r Half of the ECDSA signature pair
* @param s Half of the ECDSA signature pair
*/
function delegateBySig(
address delegatee,
uint nonce,
uint expiry,
uint8 v,
bytes32 r,
bytes32 s
)
external
{
bytes32 domainSeparator = keccak256(
abi.encode(
DOMAIN_TYPEHASH,
keccak256(bytes(name)),
getChainId(),
address(this)
)
);
bytes32 structHash = keccak256(
abi.encode(
DELEGATION_TYPEHASH,
delegatee,
nonce,
expiry
)
);
bytes32 digest = keccak256(
abi.encodePacked(
"\x19\x01",
domainSeparator,
structHash
)
);
address signatory = ecrecover(digest, v, r, s);
require(signatory != address(0), "YAM::delegateBySig: invalid signature");
require(nonce == nonces[signatory]++, "YAM::delegateBySig: invalid nonce");
require(now <= expiry, "YAM::delegateBySig: signature expired");
return _delegate(signatory, delegatee);
}
/**
* @notice Gets the current votes balance for `account`
* @param account The address to get votes balance
* @return The number of current votes for `account`
*/
function getCurrentVotes(address account)
external
view
returns (uint256)
{
uint32 nCheckpoints = numCheckpoints[account];
return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;
}
/**
* @notice Determine the prior number of votes for an account as of a block number
* @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
* @param account The address of the account to check
* @param blockNumber The block number to get the vote balance at
* @return The number of votes the account had as of the given block
*/
function getPriorVotes(address account, uint blockNumber)
external
view
returns (uint256)
{
require(blockNumber < block.number, "YAM::getPriorVotes: not yet determined");
uint32 nCheckpoints = numCheckpoints[account];
if (nCheckpoints == 0) {
return 0;
}
// First check most recent balance
if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {
return checkpoints[account][nCheckpoints - 1].votes;
}
// Next check implicit zero balance
if (checkpoints[account][0].fromBlock > blockNumber) {
return 0;
}
uint32 lower = 0;
uint32 upper = nCheckpoints - 1;
while (upper > lower) {
uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
Checkpoint memory cp = checkpoints[account][center];
if (cp.fromBlock == blockNumber) {
return cp.votes;
} else if (cp.fromBlock < blockNumber) {
lower = center;
} else {
upper = center - 1;
}
}
return checkpoints[account][lower].votes;
}
function _delegate(address delegator, address delegatee)
internal
{
address currentDelegate = _delegates[delegator];
uint256 delegatorBalance = _yamBalances[delegator]; // balance of underlying YAMs (not scaled);
_delegates[delegator] = delegatee;
emit DelegateChanged(delegator, currentDelegate, delegatee);
_moveDelegates(currentDelegate, delegatee, delegatorBalance);
}
function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal {
if (srcRep != dstRep && amount > 0) {
if (srcRep != address(0)) {
// decrease old representative
uint32 srcRepNum = numCheckpoints[srcRep];
uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;
uint256 srcRepNew = srcRepOld.sub(amount);
_writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
}
if (dstRep != address(0)) {
// increase new representative
uint32 dstRepNum = numCheckpoints[dstRep];
uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;
uint256 dstRepNew = dstRepOld.add(amount);
_writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
}
}
}
function _writeCheckpoint(
address delegatee,
uint32 nCheckpoints,
uint256 oldVotes,
uint256 newVotes
)
internal
{
uint32 blockNumber = safe32(block.number, "YAM::_writeCheckpoint: block number exceeds 32 bits");
if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {
checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;
} else {
checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);
numCheckpoints[delegatee] = nCheckpoints + 1;
}
emit DelegateVotesChanged(delegatee, oldVotes, newVotes);
}
function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {
require(n < 2**32, errorMessage);
return uint32(n);
}
function getChainId() internal pure returns (uint) {
uint256 chainId;
assembly { chainId := chainid() }
return chainId;
}
}
contract YAMToken is YAMGovernanceToken {
// Modifiers
modifier onlyGov() {
require(msg.sender == gov);
_;
}
modifier onlyRebaser() {
require(msg.sender == rebaser);
_;
}
modifier onlyMinter() {
require(msg.sender == rebaser || msg.sender == incentivizer || msg.sender == gov, "not minter");
_;
}
modifier validRecipient(address to) {
require(to != address(0x0));
require(to != address(this));
_;
}
function initialize(
string memory name_,
string memory symbol_,
uint8 decimals_
)
public
{
require(yamsScalingFactor == 0, "already initialized");
name = name_;
symbol = symbol_;
decimals = decimals_;
}
/**
* @notice Computes the current max scaling factor
*/
function maxScalingFactor()
external
view
returns (uint256)
{
return _maxScalingFactor();
}
function _maxScalingFactor()
internal
view
returns (uint256)
{
// scaling factor can only go up to 2**256-1 = initSupply * yamsScalingFactor
// this is used to check if yamsScalingFactor will be too high to compute balances when rebasing.
return uint256(-1) / initSupply;
}
/**
* @notice Mints new tokens, increasing totalSupply, initSupply, and a users balance.
* @dev Limited to onlyMinter modifier
*/
function mint(address to, uint256 amount)
external
onlyMinter
returns (bool)
{
_mint(to, amount);
return true;
}
function _mint(address to, uint256 amount)
internal
{
// increase totalSupply
totalSupply = totalSupply.add(amount);
// get underlying value
uint256 yamValue = amount.mul(internalDecimals).div(yamsScalingFactor);
// increase initSupply
initSupply = initSupply.add(yamValue);
// make sure the mint didnt push maxScalingFactor too low
require(yamsScalingFactor <= _maxScalingFactor(), "max scaling factor too low");
// add balance
_yamBalances[to] = _yamBalances[to].add(yamValue);
// add delegates to the minter
_moveDelegates(address(0), _delegates[to], yamValue);
emit Mint(to, amount);
}
/* - ERC20 functionality - */
/**
* @dev Transfer tokens to a specified address.
* @param to The address to transfer to.
* @param value The amount to be transferred.
* @return True on success, false otherwise.
*/
function transfer(address to, uint256 value)
external
validRecipient(to)
returns (bool)
{
// underlying balance is stored in yams, so divide by current scaling factor
// note, this means as scaling factor grows, dust will be untransferrable.
// minimum transfer value == yamsScalingFactor / 1e24;
// get amount in underlying
uint256 yamValue = value.mul(internalDecimals).div(yamsScalingFactor);
// sub from balance of sender
_yamBalances[msg.sender] = _yamBalances[msg.sender].sub(yamValue);
// add to balance of receiver
_yamBalances[to] = _yamBalances[to].add(yamValue);
emit Transfer(msg.sender, to, value);
_moveDelegates(_delegates[msg.sender], _delegates[to], yamValue);
return true;
}
/**
* @dev Transfer tokens from one address to another.
* @param from The address you want to send tokens from.
* @param to The address you want to transfer to.
* @param value The amount of tokens to be transferred.
*/
function transferFrom(address from, address to, uint256 value)
external
validRecipient(to)
returns (bool)
{
// decrease allowance
_allowedFragments[from][msg.sender] = _allowedFragments[from][msg.sender].sub(value);
// get value in yams
uint256 yamValue = value.mul(internalDecimals).div(yamsScalingFactor);
// sub from from
_yamBalances[from] = _yamBalances[from].sub(yamValue);
_yamBalances[to] = _yamBalances[to].add(yamValue);
emit Transfer(from, to, value);
_moveDelegates(_delegates[from], _delegates[to], yamValue);
return true;
}
/**
* @param who The address to query.
* @return The balance of the specified address.
*/
function balanceOf(address who)
external
view
returns (uint256)
{
return _yamBalances[who].mul(yamsScalingFactor).div(internalDecimals);
}
/** @notice Currently returns the internal storage amount
* @param who The address to query.
* @return The underlying balance of the specified address.
*/
function balanceOfUnderlying(address who)
external
view
returns (uint256)
{
return _yamBalances[who];
}
/**
* @dev Function to check the amount of tokens that an owner has allowed to a spender.
* @param owner_ The address which owns the funds.
* @param spender The address which will spend the funds.
* @return The number of tokens still available for the spender.
*/
function allowance(address owner_, address spender)
external
view
returns (uint256)
{
return _allowedFragments[owner_][spender];
}
/**
* @dev Approve the passed address to spend the specified amount of tokens on behalf of
* msg.sender. This method is included for ERC20 compatibility.
* increaseAllowance and decreaseAllowance should be used instead.
* Changing an allowance with this method brings the risk that someone may transfer both
* the old and the new allowance - if they are both greater than zero - if a transfer
* transaction is mined before the later approve() call is mined.
*
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
*/
function approve(address spender, uint256 value)
external
returns (bool)
{
_allowedFragments[msg.sender][spender] = value;
emit Approval(msg.sender, spender, value);
return true;
}
/**
* @dev Increase the amount of tokens that an owner has allowed to a spender.
* This method should be used instead of approve() to avoid the double approval vulnerability
* described above.
* @param spender The address which will spend the funds.
* @param addedValue The amount of tokens to increase the allowance by.
*/
function increaseAllowance(address spender, uint256 addedValue)
external
returns (bool)
{
_allowedFragments[msg.sender][spender] =
_allowedFragments[msg.sender][spender].add(addedValue);
emit Approval(msg.sender, spender, _allowedFragments[msg.sender][spender]);
return true;
}
/**
* @dev Decrease the amount of tokens that an owner has allowed to a spender.
*
* @param spender The address which will spend the funds.
* @param subtractedValue The amount of tokens to decrease the allowance by.
*/
function decreaseAllowance(address spender, uint256 subtractedValue)
external
returns (bool)
{
uint256 oldValue = _allowedFragments[msg.sender][spender];
if (subtractedValue >= oldValue) {
_allowedFragments[msg.sender][spender] = 0;
} else {
_allowedFragments[msg.sender][spender] = oldValue.sub(subtractedValue);
}
emit Approval(msg.sender, spender, _allowedFragments[msg.sender][spender]);
return true;
}
/* - Governance Functions - */
/** @notice sets the rebaser
* @param rebaser_ The address of the rebaser contract to use for authentication.
*/
function _setRebaser(address rebaser_)
external
onlyGov
{
address oldRebaser = rebaser;
rebaser = rebaser_;
emit NewRebaser(oldRebaser, rebaser_);
}
/** @notice sets the incentivizer
* @param incentivizer_ The address of the rebaser contract to use for authentication.
*/
function _setIncentivizer(address incentivizer_)
external
onlyGov
{
address oldIncentivizer = incentivizer;
incentivizer = incentivizer_;
emit NewIncentivizer(oldIncentivizer, incentivizer_);
}
/** @notice sets the pendingGov
* @param pendingGov_ The address of the rebaser contract to use for authentication.
*/
function _setPendingGov(address pendingGov_)
external
onlyGov
{
address oldPendingGov = pendingGov;
pendingGov = pendingGov_;
emit NewPendingGov(oldPendingGov, pendingGov_);
}
/** @notice lets msg.sender accept governance
*
*/
function _acceptGov()
external
{
require(msg.sender == pendingGov, "!pending");
address oldGov = gov;
gov = pendingGov;
pendingGov = address(0);
emit NewGov(oldGov, gov);
}
/* - Extras - */
/**
* @notice Initiates a new rebase operation, provided the minimum time period has elapsed.
*
* @dev The supply adjustment equals (totalSupply * DeviationFromTargetRate) / rebaseLag
* Where DeviationFromTargetRate is (MarketOracleRate - targetRate) / targetRate
* and targetRate is CpiOracleRate / baseCpi
*/
function rebase(
uint256 epoch,
uint256 indexDelta,
bool positive
)
external
onlyRebaser
returns (uint256)
{
if (indexDelta == 0) {
emit Rebase(epoch, yamsScalingFactor, yamsScalingFactor);
return totalSupply;
}
uint256 prevYamsScalingFactor = yamsScalingFactor;
if (!positive) {
yamsScalingFactor = yamsScalingFactor.mul(BASE.sub(indexDelta)).div(BASE);
} else {
uint256 newScalingFactor = yamsScalingFactor.mul(BASE.add(indexDelta)).div(BASE);
if (newScalingFactor < _maxScalingFactor()) {
yamsScalingFactor = newScalingFactor;
} else {
yamsScalingFactor = _maxScalingFactor();
}
}
totalSupply = initSupply.mul(yamsScalingFactor).div(BASE);
emit Rebase(epoch, prevYamsScalingFactor, yamsScalingFactor);
return totalSupply;
}
}
contract YAM is YAMToken {
/**
* @notice Initialize the new money market
* @param name_ ERC-20 name of this token
* @param symbol_ ERC-20 symbol of this token
* @param decimals_ ERC-20 decimal precision of this token
*/
function initialize(
string memory name_,
string memory symbol_,
uint8 decimals_,
address initial_owner,
uint256 initSupply_
)
public
{
require(initSupply_ > 0, "0 init supply");
super.initialize(name_, symbol_, decimals_);
initSupply = initSupply_.mul(10**24/ (BASE));
totalSupply = initSupply_;
yamsScalingFactor = BASE;
_yamBalances[initial_owner] = initSupply_.mul(10**24 / (BASE));
// owner renounces ownership after deployment as they need to set
// rebaser and incentivizer
// gov = gov_;
}
}
contract YAMDelegationStorage {
/**
* @notice Implementation address for this contract
*/
address public implementation;
}
contract YAMDelegateInterface is YAMDelegationStorage {
/**
* @notice Called by the delegator on a delegate to initialize it for duty
* @dev Should revert if any issues arise which make it unfit for delegation
* @param data The encoded bytes data for any initialization
*/
function _becomeImplementation(bytes memory data) public;
/**
* @notice Called by the delegator on a delegate to forfeit its responsibility
*/
function _resignImplementation() public;
}
contract SHRIMPDelegate is YAM, YAMDelegateInterface {
/**
* @notice Construct an empty delegate
*/
constructor() public {}
/**
* @notice Called by the delegator on a delegate to initialize it for duty
* @param data The encoded bytes data for any initialization
*/
function _becomeImplementation(bytes memory data) public {
// Shh -- currently unused
data;
// Shh -- we don't ever want this hook to be marked pure
if (false) {
implementation = address(0);
}
require(msg.sender == gov, "only the gov may call _becomeImplementation");
}
/**
* @notice Called by the delegator on a delegate to forfeit its responsibility
*/
function _resignImplementation() public {
// Shh -- we don't ever want this hook to be marked pure
if (false) {
implementation = address(0);
}
require(msg.sender == gov, "only the gov may call _resignImplementation");
}
}