LYPTUS vs EGG code

Created Diff never expires
23 removals
254 lines
10 additions
242 lines
pragma solidity 0.6.12;
pragma solidity 0.6.12;


// .----------------. .----------------. .----------------. .----------------. .----------------.
import "./libs/BEP20.sol";
// | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. |
// | | ___ ____ | || | ____ | || | __ | || | _____ | || | __ | |
// | | |_ ||_ _| | || | .' `. | || | / \ | || | |_ _| | || | / \ | |
// | | | |_/ / | || | / .--. \ | || | / /\ \ | || | | | | || | / /\ \ | |
// | | | __'. | || | | | | | | || | / ____ \ | || | | | _ | || | / ____ \ | |
// | | _| | \ \_ | || | \ `--' / | || | _/ / \ \_ | || | _| |__/ | | || | _/ / \ \_ | |
// | | |____||____| | || | `.____.' | || ||____| |____|| || | |________| | || ||____| |____|| |
// | | | || | | || | | || | | || | | |
// | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' |
// '----------------' '----------------' '----------------' '----------------' '----------------'


import "./BEP20.sol";
// EggToken with Governance.

contract EggToken is BEP20('Goose Golden Egg', 'EGG') {
// LyptusToken with Governance.
contract LyptusToken is BEP20('Lyptus Token', 'LYPTUS') {
/// @notice Creates `_amount` token to `_to`. Must only be called by the owner (MasterChef).
/// @notice Creates `_amount` token to `_to`. Must only be called by the owner (MasterChef).
function mint(address _to, uint256 _amount) public onlyOwner {
function mint(address _to, uint256 _amount) public onlyOwner {
_mint(_to, _amount);
_mint(_to, _amount);
_moveDelegates(address(0), _delegates[_to], _amount);
_moveDelegates(address(0), _delegates[_to], _amount);
}
}


// Copied and modified from YAM code:
// Copied and modified from YAM code:
// https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernanceStorage.sol
// https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernanceStorage.sol
// https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernance.sol
// https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernance.sol
// Which is copied and modified from COMPOUND:
// Which is copied and modified from COMPOUND:
// https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol
// https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol


/// @notice A record of each accounts delegate
/// @notice A record of each accounts delegate
mapping (address => address) internal _delegates;
mapping (address => address) internal _delegates;


/// @notice A checkpoint for marking number of votes from a given block
/// @notice A checkpoint for marking number of votes from a given block
struct Checkpoint {
struct Checkpoint {
uint32 fromBlock;
uint32 fromBlock;
uint256 votes;
uint256 votes;
}
}


/// @notice A record of votes checkpoints for each account, by index
/// @notice A record of votes checkpoints for each account, by index
mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;
mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;


/// @notice The number of checkpoints for each account
/// @notice The number of checkpoints for each account
mapping (address => uint32) public numCheckpoints;
mapping (address => uint32) public numCheckpoints;


/// @notice The EIP-712 typehash for the contract's domain
/// @notice The EIP-712 typehash for the contract's domain
bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");
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
/// @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)");
bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");


/// @notice A record of states for signing / validating signatures
/// @notice A record of states for signing / validating signatures
mapping (address => uint) public nonces;
mapping (address => uint) public nonces;


/// @notice An event thats emitted when an account changes its delegate
/// @notice An event thats emitted when an account changes its delegate
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);


/// @notice An event thats emitted when a delegate account's vote balance changes
/// @notice An event thats emitted when a delegate account's vote balance changes
event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);
event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);


/**
/**
* @notice Delegate votes from `msg.sender` to `delegatee`
* @notice Delegate votes from `msg.sender` to `delegatee`
* @param delegator The address to get delegatee for
* @param delegator The address to get delegatee for
*/
*/
function delegates(address delegator)
function delegates(address delegator)
external
external
view
view
returns (address)
returns (address)
{
{
return _delegates[delegator];
return _delegates[delegator];
}
}


/**
/**
* @notice Delegate votes from `msg.sender` to `delegatee`
* @notice Delegate votes from `msg.sender` to `delegatee`
* @param delegatee The address to delegate votes to
* @param delegatee The address to delegate votes to
*/
*/
function delegate(address delegatee) external {
function delegate(address delegatee) external {
return _delegate(msg.sender, delegatee);
return _delegate(msg.sender, delegatee);
}
}


/**
/**
* @notice Delegates votes from signatory to `delegatee`
* @notice Delegates votes from signatory to `delegatee`
* @param delegatee The address to delegate votes to
* @param delegatee The address to delegate votes to
* @param nonce The contract state required to match the signature
* @param nonce The contract state required to match the signature
* @param expiry The time at which to expire the signature
* @param expiry The time at which to expire the signature
* @param v The recovery byte of the signature
* @param v The recovery byte of the signature
* @param r Half of the ECDSA signature pair
* @param r Half of the ECDSA signature pair
* @param s Half of the ECDSA signature pair
* @param s Half of the ECDSA signature pair
*/
*/
function delegateBySig(
function delegateBySig(
address delegatee,
address delegatee,
uint nonce,
uint nonce,
uint expiry,
uint expiry,
uint8 v,
uint8 v,
bytes32 r,
bytes32 r,
bytes32 s
bytes32 s
)
)
external
external
{
{
bytes32 domainSeparator = keccak256(
bytes32 domainSeparator = keccak256(
abi.encode(
abi.encode(
DOMAIN_TYPEHASH,
DOMAIN_TYPEHASH,
keccak256(bytes(name())),
keccak256(bytes(name())),
getChainId(),
getChainId(),
address(this)
address(this)
)
)
);
);


bytes32 structHash = keccak256(
bytes32 structHash = keccak256(
abi.encode(
abi.encode(
DELEGATION_TYPEHASH,
DELEGATION_TYPEHASH,
delegatee,
delegatee,
nonce,
nonce,
expiry
expiry
)
)
);
);


bytes32 digest = keccak256(
bytes32 digest = keccak256(
abi.encodePacked(
abi.encodePacked(
"\x19\x01",
"\x19\x01",
domainSeparator,
domainSeparator,
structHash
structHash
)
)
);
);


address signatory = ecrecover(digest, v, r, s);
address signatory = ecrecover(digest, v, r, s);
require(signatory != address(0), "LYPTUS::delegateBySig: invalid signature");
require(signatory != address(0), "EGG::delegateBySig: invalid signature");
require(nonce == nonces[signatory]++, "LYPTUS::delegateBySig: invalid nonce");
require(nonce == nonces[signatory]++, "EGG::delegateBySig: invalid nonce");
require(now <= expiry, "LYPTUS::delegateBySig: signature expired");
require(now <= expiry, "EGG::delegateBySig: signature expired");
return _delegate(signatory, delegatee);
return _delegate(signatory, delegatee);
}
}


/**
/**
* @notice Gets the current votes balance for `account`
* @notice Gets the current votes balance for `account`
* @param account The address to get votes balance
* @param account The address to get votes balance
* @return The number of current votes for `account`
* @return The number of current votes for `account`
*/
*/
function getCurrentVotes(address account)
function getCurrentVotes(address account)
external
external
view
view
returns (uint256)
returns (uint256)
{
{
uint32 nCheckpoints = numCheckpoints[account];
uint32 nCheckpoints = numCheckpoints[account];
return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;
return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;
}
}


/**
/**
* @notice Determine the prior number of votes for an account as of a block number
* @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.
* @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 account The address of the account to check
* @param blockNumber The block number to get the vote balance at
* @param blockNumber The block number to get the vote balance at
* @return The number of votes the account had as of the given block
* @return The number of votes the account had as of the given block
*/
*/
function getPriorVotes(address account, uint blockNumber)
function getPriorVotes(address account, uint blockNumber)
external
external
view
view
returns (uint256)
returns (uint256)
{
{
require(blockNumber < block.number, "LYPTUS::getPriorVotes: not yet determined");
require(blockNumber < block.number, "EGG::getPriorVotes: not yet determined");


uint32 nCheckpoints = numCheckpoints[account];
uint32 nCheckpoints = numCheckpoints[account];
if (nCheckpoints == 0) {
if (nCheckpoints == 0) {
return 0;
return 0;
}
}


// First check most recent balance
// First check most recent balance
if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {
if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {
return checkpoints[account][nCheckpoints - 1].votes;
return checkpoints[account][nCheckpoints - 1].votes;
}
}


// Next check implicit zero balance
// Next check implicit zero balance
if (checkpoints[account][0].fromBlock > blockNumber) {
if (checkpoints[account][0].fromBlock > blockNumber) {
return 0;
return 0;
}
}


uint32 lower = 0;
uint32 lower = 0;
uint32 upper = nCheckpoints - 1;
uint32 upper = nCheckpoints - 1;
while (upper > lower) {
while (upper > lower) {
uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
Checkpoint memory cp = checkpoints[account][center];
Checkpoint memory cp = checkpoints[account][center];
if (cp.fromBlock == blockNumber) {
if (cp.fromBlock == blockNumber) {
return cp.votes;
return cp.votes;
} else if (cp.fromBlock < blockNumber) {
} else if (cp.fromBlock < blockNumber) {
lower = center;
lower = center;
} else {
} else {
upper = center - 1;
upper = center - 1;
}
}
}
}
return checkpoints[account][lower].votes;
return checkpoints[account][lower].votes;
}
}


function _delegate(address delegator, address delegatee)
function _delegate(address delegator, address delegatee)
internal
internal
{
{
address currentDelegate = _delegates[delegator];
address currentDelegate = _delegates[delegator];
uint256 delegatorBalance = balanceOf(delegator); // balance of underlying LYPTUSs (not scaled);
uint256 delegatorBalance = balanceOf(delegator); // balance of underlying EGGs (not scaled);
_delegates[delegator] = delegatee;
_delegates[delegator] = delegatee;


emit DelegateChanged(delegator, currentDelegate, delegatee);
emit DelegateChanged(delegator, currentDelegate, delegatee);


_moveDelegates(currentDelegate, delegatee, delegatorBalance);
_moveDelegates(currentDelegate, delegatee, delegatorBalance);
}
}


function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal {
function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal {
if (srcRep != dstRep && amount > 0) {
if (srcRep != dstRep && amount > 0) {
if (srcRep != address(0)) {
if (srcRep != address(0)) {
// decrease old representative
// decrease old representative
uint32 srcRepNum = numCheckpoints[srcRep];
uint32 srcRepNum = numCheckpoints[srcRep];
uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;
uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;
uint256 srcRepNew = srcRepOld.sub(amount);
uint256 srcRepNew = srcRepOld.sub(amount);
_writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
_writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
}
}


if (dstRep != address(0)) {
if (dstRep != address(0)) {
// increase new representative
// increase new representative
uint32 dstRepNum = numCheckpoints[dstRep];
uint32 dstRepNum = numCheckpoints[dstRep];
uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;
uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;
uint256 dstRepNew = dstRepOld.add(amount);
uint256 dstRepNew = dstRepOld.add(amount);
_writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
_writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
}
}
}
}
}
}


function _writeCheckpoint(
function _writeCheckpoint(
address delegatee,
address delegatee,
uint32 nCheckpoints,
uint32 nCheckpoints,
uint256 oldVotes,
uint256 oldVotes,
uint256 newVotes
uint256 newVotes
)
)
internal
internal
{
{
uint32 blockNumber = safe32(block.number, "LYPTUS::_writeCheckpoint: block number exceeds 32 bits");
uint32 blockNumber = safe32(block.number, "EGG::_writeCheckpoint: block number exceeds 32 bits");


if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {
if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {
checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;
checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;
} else {
} else {
checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);
checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);
numCheckpoints[delegatee] = nCheckpoints + 1;
numCheckpoints[delegatee] = nCheckpoints + 1;
}
}


emit DelegateVotesChanged(delegatee, oldVotes, newVotes);
emit DelegateVotesChanged(delegatee, oldVotes, newVotes);
}
}


function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {
function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {
require(n < 2**32, errorMessage);
require(n < 2**32, errorMessage);
return uint32(n);
return uint32(n);
}
}


function getChainId() internal pure returns (uint) {
function getChainId() internal pure returns (uint) {
uint256 chainId;
uint256 chainId;
assembly { chainId := chainid() }
assembly { chainId := chainid() }
return chainId;
return chainId;
}
}
}
}