// SPDX-License-Identifier: MITpragmasolidity ^0.5.17;/**
* @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.
*/librarySafeMath{
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/functionadd(uint256 a, uint256 b) internalpurereturns (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.
*/functionsub(uint256 a, uint256 b) internalpurereturns (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.
*/functionsub(uint256 a, uint256 b, stringmemory errorMessage) internalpurereturns (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.
*/functionmul(uint256 a, uint256 b) internalpurereturns (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/522if (a ==0) {
return0;
}
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.
*/functiondiv(uint256 a, uint256 b) internalpurereturns (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.
*/functiondiv(uint256 a, uint256 b, stringmemory errorMessage) internalpurereturns (uint256) {
require(b >0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't holdreturn 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.
*/functionmod(uint256 a, uint256 b) internalpurereturns (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.
*/functionmod(uint256 a, uint256 b, stringmemory errorMessage) internalpurereturns (uint256) {
require(b !=0, errorMessage);
return a % b;
}
}
Contract Source Code
File 4 of 11: VELO.sol
pragmasolidity 0.5.17;/* import "./VELOTokenInterface.sol"; */import"./VELOGovernance.sol";
import"../feeCharger/VELOFeeCharger.sol";
import"../lib/IRebaser.sol";
libraryMath{
/**
* @dev Returns the largest of two numbers.
*/functionmax(uint256 a, uint256 b) internalpurereturns (uint256) {
return a >= b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/functionmin(uint256 a, uint256 b) internalpurereturns (uint256) {
return a < b ? a : b;
}
}
contractVELOTokenisVELOGovernanceToken{
// ModifiersmodifieronlyGov() {
require(msg.sender== gov);
_;
}
modifieronlyRebaser() {
require(msg.sender== rebaser);
_;
}
modifieronlyMinter() {
require(msg.sender== rebaser ||msg.sender== gov, "not minter");
_;
}
modifiervalidRecipient(address to) {
require(to !=address(0x0));
require(to !=address(this));
_;
}
functioninitialize(stringmemory name_,
stringmemory symbol_,
uint8 decimals_
)
public{
require(velosScalingFactor ==0, "already initialized");
name = name_;
symbol = symbol_;
decimals = decimals_;
}
/**
* @notice Computes the current max scaling factor
*/functionmaxScalingFactor()
externalviewreturns (uint256)
{
return _maxScalingFactor();
}
function_maxScalingFactor()
internalviewreturns (uint256)
{
// scaling factor can only go up to 2**256-1 = initSupply * velosScalingFactor// this is used to check if velosScalingFactor will be too high to compute balances when rebasing.returnuint256(-1) / initSupply;
}
/**
* @notice Mints new tokens, increasing totalSupply, initSupply, and a users balance.
* @dev Limited to onlyMinter modifier
*/functionmint(address to, uint256 amount)
externalonlyMinterreturns (bool)
{
_mint(to, amount);
returntrue;
}
function_mint(address to, uint256 amount)
internal{
// increase totalSupply
totalSupply = totalSupply.add(amount);
// get underlying valueuint256 veloValue = amount.mul(internalDecimals).div(velosScalingFactor);
// increase initSupply
initSupply = initSupply.add(veloValue);
// make sure the mint didnt push maxScalingFactor too lowrequire(velosScalingFactor <= _maxScalingFactor(), "max scaling factor too low");
// add balance
_veloBalances[to] = _veloBalances[to].add(veloValue);
// add delegates to the minter
_moveDelegates(address(0), _delegates[to], veloValue);
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.
*/functiontransfer(address to, uint256 value)
externalvalidRecipient(to)
returns (bool)
{
// underlying balance is stored in velos, so divide by current scaling factor// note, this means as scaling factor grows, dust will be untransferrable.// minimum transfer value == velosScalingFactor / 1e24;// get amount in underlyinguint256 veloValue = value.mul(internalDecimals).div(velosScalingFactor);
// sub from balance of sender
_veloBalances[msg.sender] = _veloBalances[msg.sender].sub(veloValue);
// add to balance of receiver
_veloBalances[to] = _veloBalances[to].add(veloValue);
emit Transfer(msg.sender, to, value);
_moveDelegates(_delegates[msg.sender], _delegates[to], veloValue);
// this avoids building up velocity// when deployting the contractif(msg.sender!= gov) {
IRebaser rb = IRebaser(rebaser);
rb.registerVelocity(value);
VELOFeeCharger(feeCharger).chargeFee(rb.fEMA(), rb.sEMA(), totalSupply, value);
}
returntrue;
}
/**
* @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.
*/functiontransferFrom(addressfrom, address to, uint256 value)
externalvalidRecipient(to)
returns (bool)
{
// decrease allowance, boundaries are enforced by SafeMath and the usage// of uint256
_allowedFragments[from][msg.sender] = _allowedFragments[from][msg.sender]
.sub(value);
// get value in velosuint256 veloValue = value.mul(internalDecimals).div(velosScalingFactor);
// sub from from
_veloBalances[from] = _veloBalances[from].sub(veloValue);
_veloBalances[to] = _veloBalances[to].add(veloValue);
emit Transfer(from, to, value);
_moveDelegates(_delegates[from], _delegates[to], veloValue);
// we do not want to count velocity on initial// distribution, or when gov is moving tokensif(msg.sender!= gov) {
IRebaser rb = IRebaser(rebaser);
rb.registerVelocity(value);
VELOFeeCharger(feeCharger).chargeFee(rb.fEMA(), rb.sEMA(), totalSupply, value);
}
returntrue;
}
/**
* @param who The address to query.
* @return The balance of the specified address.
*/functionbalanceOf(address who)
externalviewreturns (uint256)
{
return _veloBalances[who].mul(velosScalingFactor).div(internalDecimals);
}
/** @notice Currently returns the internal storage amount
* @param who The address to query.
* @return The underlying balance of the specified address.
*/functionbalanceOfUnderlying(address who)
externalviewreturns (uint256)
{
return _veloBalances[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.
*/functionallowance(address owner_, address spender)
externalviewreturns (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.
*/functionapprove(address spender, uint256 value)
externalreturns (bool)
{
_allowedFragments[msg.sender][spender] = value;
emit Approval(msg.sender, spender, value);
returntrue;
}
/**
* @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.
*/functionincreaseAllowance(address spender, uint256 addedValue)
externalreturns (bool)
{
_allowedFragments[msg.sender][spender] =
_allowedFragments[msg.sender][spender].add(addedValue);
emit Approval(msg.sender, spender, _allowedFragments[msg.sender][spender]);
returntrue;
}
/**
* @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.
*/functiondecreaseAllowance(address spender, uint256 subtractedValue)
externalreturns (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]);
returntrue;
}
/* - Governance Functions - *//** @notice sets the rebaser
* @param rebaser_ The address of the rebaser contract to use for authentication.
*/functionsetRebaser(address rebaser_)
externalonlyGov{
address oldRebaser = rebaser;
rebaser = rebaser_;
emit NewRebaser(oldRebaser, rebaser_);
}
// FIXME: normalize the underscore usagefunctionsetFeeCharger(address feeCharger_)
externalonlyGov{
feeCharger = feeCharger_;
}
/** @notice sets the pendingGov
* @param pendingGov_ The address of the rebaser contract to use for authentication.
*/function_setPendingGov(address pendingGov_)
externalonlyGov{
address oldPendingGov = pendingGov;
pendingGov = pendingGov_;
emit NewPendingGov(oldPendingGov, pendingGov_);
}
functionsetGov(address gov_) externalonlyGov{
gov = gov_;
}
/** @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);
}
/* - Rebase function - */functionrebase(uint256 scaling_modifier)
externalonlyRebaser{
uint256 prevVelosScalingFactor = velosScalingFactor;
// velosScalingFactor is in precision 24
velosScalingFactor = velosScalingFactor
.mul(scaling_modifier)
.div(internalDecimals);
velosScalingFactor = Math.min(velosScalingFactor, 1* internalDecimals);
totalSupply = initSupply.mul(velosScalingFactor).div(internalDecimals);
emit Rebase(prevVelosScalingFactor, velosScalingFactor);
}
}
contractVELOisVELOToken{
/**
* @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
*/functioninitialize(stringmemory name_,
stringmemory 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_;
velosScalingFactor = BASE;
_veloBalances[initial_owner] = initSupply_; //.mul(10**24 / (BASE));emit Transfer(address(0), msg.sender, initSupply_);
// owner renounces ownership after deployment as they need to set// rebaser and incentivizer// gov = gov_;
}
}
Contract Source Code
File 5 of 11: VELODelegate.sol
pragmasolidity 0.5.17;import"./VELO.sol";
contractVELODelegationStorage{
/**
* @notice Implementation address for this contract
*/addresspublic implementation;
}
contractVELODelegatorInterfaceisVELODelegationStorage{
/**
* @notice Emitted when implementation is changed
*/eventNewImplementation(address oldImplementation, address newImplementation);
/**
* @notice Called by the gov to update the implementation of the delegator
* @param implementation_ The address of the new implementation for delegation
* @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation
* @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation
*/function_setImplementation(address implementation_, bool allowResign, bytesmemory becomeImplementationData) public;
}
contractVELODelegateInterfaceisVELODelegationStorage{
/**
* @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(bytesmemory data) public;
/**
* @notice Called by the delegator on a delegate to forfeit its responsibility
*/function_resignImplementation() public;
}
contractVELODelegateisVELO, VELODelegateInterface{
/**
* @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(bytesmemory data) public{
// Shh -- currently unused
data;
// Shh -- we don't ever want this hook to be marked pureif (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 pureif (false) {
implementation =address(0);
}
require(msg.sender== gov, "only the gov may call _resignImplementation");
}
}
Contract Source Code
File 6 of 11: VELODelegator.sol
pragmasolidity 0.5.17;import"./VELOTokenInterface.sol";
import"./VELODelegate.sol";
contractVELODelegatorisVELOTokenInterface, VELODelegatorInterface{
/**
* @notice Construct a new VELO
* @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
* @param initSupply_ Initial token amount
* @param implementation_ The address of the implementation the contract delegates to
* @param becomeImplementationData The encoded args for becomeImplementation
*/constructor(stringmemory name_,
stringmemory symbol_,
uint8 decimals_,
uint256 initSupply_,
address implementation_,
bytesmemory becomeImplementationData
)
public{
// Creator of the contract is gov during initialization
gov =msg.sender;
// First delegate gets to initialize the delegator (i.e. storage contract)
delegateTo(
implementation_,
abi.encodeWithSignature(
"initialize(string,string,uint8,address,uint256)",
name_,
symbol_,
decimals_,
msg.sender,
initSupply_
)
);
// New implementations always get set via the settor (post-initialize)
_setImplementation(implementation_, false, becomeImplementationData);
}
/**
* @notice Called by the gov to update the implementation of the delegator
* @param implementation_ The address of the new implementation for delegation
* @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation
* @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation
*/function_setImplementation(address implementation_, bool allowResign, bytesmemory becomeImplementationData) public{
require(msg.sender== gov, "VELODelegator::_setImplementation: Caller must be gov");
if (allowResign) {
delegateToImplementation(abi.encodeWithSignature("_resignImplementation()"));
}
address oldImplementation = implementation;
implementation = implementation_;
delegateToImplementation(abi.encodeWithSignature("_becomeImplementation(bytes)", becomeImplementationData));
emit NewImplementation(oldImplementation, implementation);
}
/**
* @notice Sender supplies assets into the market and receives cTokens in exchange
* @dev Accrues interest whether or not the operation succeeds, unless reverted
* @param mintAmount The amount of the underlying asset to supply
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/functionmint(address to, uint256 mintAmount)
externalreturns (bool)
{
to; mintAmount; // Shh
delegateAndReturn();
}
/**
* @notice Transfer `amount` tokens from `msg.sender` to `dst`
* @param dst The address of the destination account
* @param amount The number of tokens to transfer
* @return Whether or not the transfer succeeded
*/functiontransfer(address dst, uint256 amount)
externalreturns (bool)
{
dst; amount; // Shh
delegateAndReturn();
}
/**
* @notice Transfer `amount` tokens from `src` to `dst`
* @param src The address of the source account
* @param dst The address of the destination account
* @param amount The number of tokens to transfer
* @return Whether or not the transfer succeeded
*/functiontransferFrom(address src,
address dst,
uint256 amount
)
externalreturns (bool)
{
src; dst; amount; // Shh
delegateAndReturn();
}
/**
* @notice Approve `spender` to transfer up to `amount` from `src`
* @dev This will overwrite the approval amount for `spender`
* and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)
* @param spender The address of the account which may transfer tokens
* @param amount The number of tokens that are approved (-1 means infinite)
* @return Whether or not the approval succeeded
*/functionapprove(address spender,
uint256 amount
)
externalreturns (bool)
{
spender; amount; // Shh
delegateAndReturn();
}
/**
* @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.
*/functionincreaseAllowance(address spender,
uint256 addedValue
)
externalreturns (bool)
{
spender; addedValue; // Shh
delegateAndReturn();
}
functionmaxScalingFactor()
externalviewreturns (uint256)
{
delegateToViewAndReturn();
}
/**
* @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.
*/functiondecreaseAllowance(address spender,
uint256 subtractedValue
)
externalreturns (bool)
{
spender; subtractedValue; // Shh
delegateAndReturn();
}
/**
* @notice Get the current allowance from `owner` for `spender`
* @param owner The address of the account which owns the tokens to be spent
* @param spender The address of the account which may transfer tokens
* @return The number of tokens allowed to be spent (-1 means infinite)
*/functionallowance(address owner,
address spender
)
externalviewreturns (uint256)
{
owner; spender; // Shh
delegateToViewAndReturn();
}
/**
* @notice Get the current allowance from `owner` for `spender`
* @param delegator The address of the account which has designated a delegate
* @return Address of delegatee
*/functiondelegates(address delegator
)
externalviewreturns (address)
{
delegator; // Shh
delegateToViewAndReturn();
}
/**
* @notice Get the token balance of the `owner`
* @param owner The address of the account to query
* @return The number of tokens owned by `owner`
*/functionbalanceOf(address owner)
externalviewreturns (uint256)
{
owner; // Shh
delegateToViewAndReturn();
}
/**
* @notice Currently unused. For future compatability
* @param owner The address of the account to query
* @return The number of underlying tokens owned by `owner`
*/functionbalanceOfUnderlying(address owner)
externalviewreturns (uint256)
{
owner; // Shh
delegateToViewAndReturn();
}
/*** Gov Functions ***//**
* @notice Begins transfer of gov rights. The newPendingGov must call `_acceptGov` to finalize the transfer.
* @dev Gov function to begin change of gov. The newPendingGov must call `_acceptGov` to finalize the transfer.
* @param newPendingGov New pending gov.
*/function_setPendingGov(address newPendingGov)
external{
newPendingGov; // Shh
delegateAndReturn();
}
functionsetRebaser(address rebaser_)
external{
rebaser_; // Shh
delegateAndReturn();
}
function_setIncentivizer(address incentivizer_)
external{
incentivizer_; // Shh
delegateAndReturn();
}
/**
* @notice Accepts transfer of gov rights. msg.sender must be pendingGov
* @dev Gov function for pending gov to accept role and update gov
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/function_acceptGov()
external{
delegateAndReturn();
}
functionsetGov(address gov_) external{
gov_;
delegateAndReturn();
}
functionrebase(uint256 scaling_modifier) external{
delegateAndReturn();
}
functionsetFeeCharger(address feeCharger_
) external{
feeCharger_;
delegateAndReturn();
}
functiongetPriorVotes(address account, uint blockNumber)
externalviewreturns (uint256)
{
account; blockNumber;
delegateToViewAndReturn();
}
functiondelegateBySig(address delegatee,
uint nonce,
uint expiry,
uint8 v,
bytes32 r,
bytes32 s
)
external{
delegatee; nonce; expiry; v; r; s;
delegateAndReturn();
}
functiondelegate(address delegatee)
external{
delegatee;
delegateAndReturn();
}
functiongetCurrentVotes(address account)
externalviewreturns (uint256)
{
account;
delegateToViewAndReturn();
}
/**
* @notice Internal method to delegate execution to another contract
* @dev It returns to the external caller whatever the implementation returns or forwards reverts
* @param callee The contract to delegatecall
* @param data The raw data to delegatecall
* @return The returned bytes from the delegatecall
*/functiondelegateTo(address callee, bytesmemory data) internalreturns (bytesmemory) {
(bool success, bytesmemory returnData) = callee.delegatecall(data);
assembly {
ifeq(success, 0) {
revert(add(returnData, 0x20), returndatasize)
}
}
return returnData;
}
/**
* @notice Delegates execution to the implementation contract
* @dev It returns to the external caller whatever the implementation returns or forwards reverts
* @param data The raw data to delegatecall
* @return The returned bytes from the delegatecall
*/functiondelegateToImplementation(bytesmemory data) publicreturns (bytesmemory) {
return delegateTo(implementation, data);
}
/**
* @notice Delegates execution to an implementation contract
* @dev It returns to the external caller whatever the implementation returns or forwards reverts
* There are an additional 2 prefix uints from the wrapper returndata, which we ignore since we make an extra hop.
* @param data The raw data to delegatecall
* @return The returned bytes from the delegatecall
*/functiondelegateToViewImplementation(bytesmemory data) publicviewreturns (bytesmemory) {
(bool success, bytesmemory returnData) =address(this).staticcall(abi.encodeWithSignature("delegateToImplementation(bytes)", data));
assembly {
ifeq(success, 0) {
revert(add(returnData, 0x20), returndatasize)
}
}
returnabi.decode(returnData, (bytes));
}
functiondelegateToViewAndReturn() privateviewreturns (bytesmemory) {
(bool success, ) =address(this).staticcall(abi.encodeWithSignature("delegateToImplementation(bytes)", msg.data));
assembly {
let free_mem_ptr :=mload(0x40)
returndatacopy(free_mem_ptr, 0, returndatasize)
switch success
case0 { revert(free_mem_ptr, returndatasize) }
default { return(add(free_mem_ptr, 0x40), returndatasize) }
}
}
functiondelegateAndReturn() privatereturns (bytesmemory) {
(bool success, ) = implementation.delegatecall(msg.data);
assembly {
let free_mem_ptr :=mload(0x40)
returndatacopy(free_mem_ptr, 0, returndatasize)
switch success
case0 { revert(free_mem_ptr, returndatasize) }
default { return(free_mem_ptr, returndatasize) }
}
}
/**
* @notice Delegates execution to an implementation contract
* @dev It returns to the external caller whatever the implementation returns or forwards reverts
*/function () externalpayable{
require(msg.value==0,"VELODelegator:fallback: cannot send value to fallback");
// delegate all other functions to current implementation
delegateAndReturn();
}
}
Contract Source Code
File 7 of 11: VELOFeeCharger.sol
pragmasolidity 0.5.17;import"../lib/ICHI.sol";
import {VELOTokenInterfaceasIVELO} from"../token/VELOTokenInterface.sol";
contractVELOFeeCharger{
ICHI publicconstant chi = ICHI(0x0000000000004946c0e9F43F4Dee607b0eF1fA1c);
IVELO public velo;
uint256public govFactor;
addresspublic gov;
addresspublic beneficiary;
uint256public max_gas_block;
uint256public min_gas_tx;
uint256public gov_fee_factor;
uint256public last_block_number;
uint256public chi_fee_remaining;
functionsetMaxGasBlock(uint256 value) public{
max_gas_block = value;
}
functionsetMinGasTx(uint256 value) public{
min_gas_tx = value;
}
functionsetGovFeeFactor(uint256 value) public{
gov_fee_factor = value;
}
modifieronlyGov() {
require(msg.sender== gov, "!gov");
_;
}
constructor(address velo_) public{
velo = IVELO(velo_);
// government levers
gov =msg.sender;
gov_fee_factor =1*10**18;
max_gas_block =135*10**18;
min_gas_tx =2*10**18;
// tracking amount of chi charged// in a block.
last_block_number =0;
chi_fee_remaining =0;
}
functionsetGov(address newGov) externalonlyGov{
gov = newGov;
}
functionsetGovFactor(uint256 factor) externalonlyGov{
govFactor = factor;
}
functionsetBeneficiary(address beneficiary_) externalonlyGov{
beneficiary = beneficiary_;
}
functionchargeFee(uint256 fEMA, uint256 sEMA, uint256 totalSupply, uint256 _amount) public{
uint256 chi_fee =
calc_fee_gas(max_gas_block, min_gas_tx, sEMA, _amount, totalSupply, gov_fee_factor);
// count total amount of chi charges within a block. If the current// chi_fee charged in a block overflows the max_gas_block it will be// discounted to exactly max_gas_blockif(last_block_number ==block.number) {
// protect against overflowif (chi_fee_remaining < chi_fee) {
chi_fee = chi_fee_remaining;
}
chi_fee_remaining = chi_fee_remaining - chi_fee;
} else {
last_block_number =block.number;
// the chi_fee can be maximal max_gas_block, limited// in the calc_fee_gas function. So no safe math needed// here.
chi_fee_remaining = max_gas_block - chi_fee;
}
// velo token will only allow max_gas_block to be charged// we will not charge for transactions exceeding the max_gas_block// as we do not want transactions to fail because of the minting.if (chi_fee >0&& beneficiary !=address(0x0)) {
// chi.mint needs tokens as a unit
chi.mint(chi_fee /10**18);
chi.transfer(beneficiary, chi.balanceOf(address(this)));
}
}
functioncalc_fee_ratio_discrete(uint256 ema1_vt,
uint256 ema2_vt,
uint256 tx_size,
uint256 total_supply,
uint256 _gov_fee_factor
) internalpurereturns (uint256) {
uint256 tx_discount_factor = ema2_vt;
uint256 tx_fee_ratio =10*10**18;
if(tx_size <= total_supply /596) {
tx_fee_ratio =6;
} elseif(tx_size <= total_supply /369) {
tx_fee_ratio =9;
} elseif(tx_size <= total_supply /228) {
tx_fee_ratio =15;
} elseif(tx_size <= total_supply /141) {
tx_fee_ratio =23;
} elseif(tx_size <= total_supply /87) {
tx_fee_ratio =37;
} elseif(tx_size <= total_supply /54) {
tx_fee_ratio =55;
} elseif(tx_size <= total_supply /33) {
tx_fee_ratio =76;
} elseif(tx_size <= total_supply /21) {
tx_fee_ratio =92;
} elseif(tx_size <= total_supply /13) {
tx_fee_ratio =98;
} elseif(tx_size <= total_supply /6) {
tx_fee_ratio =99;
} else {
tx_fee_ratio =100;
}
return ((tx_fee_ratio * tx_discount_factor /100) * _gov_fee_factor)
/10**18;
}
// NOTE: we return and unscaled integer between roughly// 8 and 135 to approximate the gas fee for the// velocity transactionfunctioncalc_fee_gas(uint256 max_gas_block,
uint256 min_gas_tx,
uint256 ema_long,
uint256 tx_size,
uint256 total_supply,
uint256 _gov_fee_factor
) publicpurereturns (uint256) {
uint256 max_gas_chi_per_block = max_gas_block;
uint256 min_gas_chi_fee_per_tx = min_gas_tx;
uint256 tx_fee_ratio_disc =
calc_fee_ratio_discrete(0, ema_long, tx_size, total_supply, _gov_fee_factor);
uint256 tx_fee_chi_disc =
max_gas_chi_per_block * tx_fee_ratio_disc /100/10**18;
if ( tx_fee_chi_disc < min_gas_chi_fee_per_tx ) {
tx_fee_chi_disc = min_gas_chi_fee_per_tx;
}
return tx_fee_chi_disc;
}
}
Contract Source Code
File 8 of 11: VELOGovernance.sol
pragmasolidity 0.5.17;pragmaexperimentalABIEncoderV2;import"./VELOGovernanceStorage.sol";
import"./VELOTokenInterface.sol";
contractVELOGovernanceTokenisVELOTokenInterface{
/// @notice An event thats emitted when an account changes its delegateeventDelegateChanged(addressindexed delegator, addressindexed fromDelegate, addressindexed toDelegate);
/// @notice An event thats emitted when a delegate account's vote balance changeseventDelegateVotesChanged(addressindexed delegate, uint previousBalance, uint newBalance);
/**
* @notice Delegate votes from `msg.sender` to `delegatee`
* @param delegator The address to get delegatee for
*/functiondelegates(address delegator)
externalviewreturns (address)
{
return _delegates[delegator];
}
/**
* @notice Delegate votes from `msg.sender` to `delegatee`
* @param delegatee The address to delegate votes to
*/functiondelegate(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
*/functiondelegateBySig(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), "VELO::delegateBySig: invalid signature");
require(nonce == nonces[signatory]++, "VELO::delegateBySig: invalid nonce");
require(now<= expiry, "VELO::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`
*/functiongetCurrentVotes(address account)
externalviewreturns (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
*/functiongetPriorVotes(address account, uint blockNumber)
externalviewreturns (uint256)
{
require(blockNumber <block.number, "VELO::getPriorVotes: not yet determined");
uint32 nCheckpoints = numCheckpoints[account];
if (nCheckpoints ==0) {
return0;
}
// First check most recent balanceif (checkpoints[account][nCheckpoints -1].fromBlock <= blockNumber) {
return checkpoints[account][nCheckpoints -1].votes;
}
// Next check implicit zero balanceif (checkpoints[account][0].fromBlock > blockNumber) {
return0;
}
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;
} elseif (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 = _veloBalances[delegator]; // balance of underlying VELOs (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 representativeuint32 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 representativeuint32 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, "VELO::_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);
}
functionsafe32(uint n, stringmemory errorMessage) internalpurereturns (uint32) {
require(n <2**32, errorMessage);
returnuint32(n);
}
functiongetChainId() internalpurereturns (uint) {
uint256 chainId;
assembly { chainId :=chainid() }
return chainId;
}
}
Contract Source Code
File 9 of 11: VELOGovernanceStorage.sol
pragmasolidity 0.5.17;pragmaexperimentalABIEncoderV2;contractVELOGovernanceStorage{
/// @notice A record of each accounts delegatemapping (address=>address) internal _delegates;
/// @notice A checkpoint for marking number of votes from a given blockstructCheckpoint {
uint32 fromBlock;
uint256 votes;
}
/// @notice A record of votes checkpoints for each account, by indexmapping (address=>mapping (uint32=> Checkpoint)) public checkpoints;
/// @notice The number of checkpoints for each accountmapping (address=>uint32) public numCheckpoints;
/// @notice The EIP-712 typehash for the contract's domainbytes32publicconstant DOMAIN_TYPEHASH =keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");
/// @notice The EIP-712 typehash for the delegation struct used by the contractbytes32publicconstant DELEGATION_TYPEHASH =keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");
/// @notice A record of states for signing / validating signaturesmapping (address=>uint) public nonces;
}