LYPTUS vs EGG code

Created Diff never expires
23 removals
Lines
Total
Removed
Words
Total
Removed
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
254 lines
10 additions
Lines
Total
Added
Words
Total
Added
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
242 lines
pragma solidity 0.6.12;
pragma solidity 0.6.12;


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

import "./BEP20.sol";


// LyptusToken with Governance.
// EggToken with Governance.
contract LyptusToken is BEP20('Lyptus Token', 'LYPTUS') {
contract EggToken is BEP20('Goose Golden Egg', 'EGG') {
/// @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;
}
}
}
}