Vulnerability Category | Notes | Result |
---|---|---|
Arbitrary Storage Write | N/A | PASS |
Arbitrary Jump | N/A | PASS |
Delegate Call to Untrusted Contract | N/A | PASS |
Dependence on Predictable Variables | N/A | PASS |
Deprecated Opcodes | N/A | PASS |
Ether Thief | N/A | PASS |
Exceptions | N/A | PASS |
External Calls | N/A | PASS |
Integer Over/Underflow | N/A | PASS |
Multiple Sends | N/A | PASS |
Suicide | N/A | PASS |
State Change External Calls | N/A | Pass |
Unchecked Retval | N/A | PASS |
User Supplied Assertion | A user can trigger an assertion violation on the slash() function, but their transaction will revert safely. This poses no security risk. | Warning |
Critical Solidity Compiler | N/A | PASS |
Overall Contract Safety | PASS |
yLeaf Token & Presale Audit
Summary
SourceHat Smart Contract Audits yLEAF is a new deflationary token. Its a new breed of experimental protocols based and adopting some famous project in the past. Performing a 3% deflationary burn on every transaction will make the supply scarce. The presale will be announced on the team's medium.
For this audit, we inspected yLEAF's token and presale contracts.
The contract includes all the standard ERC20 functions as defined in the ERC20 protocol by the Ethereum Foundation.
Additional features included in the contracts:Audit Findings Summary
- No minting occurs after deployment - the total supply shall only decrease.
- Burn tokens to reduce the total/circulating supply.
- Ownership - Some functions are protected and can only be called by the contract owner. You can transfer ownership to any address.
- Tokens purchased with Ether are sent directly to the purchaser's address.
- Utilization of SafeMath to prevent overflows.
- No security issues were identified.
- Date: November 22nd, 2020.
Token Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ [Lib] SafeMath
- [Int] mul
- [Int] div
- [Int] sub
- [Int] add
- [Int] ceil
+ yLEAF
- [Pub] #
- [Pub] name
- [Pub] symbol
- [Pub] decimals
- [Pub] totalSupply
- [Pub] balanceOf
- [Pub] allowance
- [Pub] slash
- [Pub] transfer #
- [Pub] increaseAllowance #
- [Pub] decreaseAllowance #
- [Int] _transfer #
- [Pub] approve #
- [Pub] transferFrom #
- [Int] _issue #
- [Ext] burn #
- [Int] _burn #
- [Ext] burnFrom #
- [Int] _mint #
- [Ext] ($)
- [Ext] ($)
Click here to download the source code as a .sol file.
//SPDX-License-Identifier: MIT
/*##################################################
* ################# yLEAF ########################
* ############ Deflationary Token #################
* ##################################################
*
* ##################################################
* #### Every Token transfer initiates a 3% Burn ####
* #### of the amount sent in each transaction. ####
* ##################################################
*
* ##################################################
* ############### 20 November 2020 ################
* ##################################################
**/
pragma solidity 0.7.5;
library SafeMath { //Safe Maths
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
assert(c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a / b;
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
function ceil(uint256 a, uint256 m) internal pure returns (uint256) {
uint256 c = add(a,m);
uint256 d = sub(c,1);
return mul(div(d,m),m);
}
}
contract yLEAF {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowed;
string constant _name = "yLEAF";
string constant _symbol = "yLEAF";
uint8 constant _decimals = 18;
uint256 private _totalSupply = 2000000000000000000000;
uint256 constant basePercent = 300;
address private ownerAddress = 0x5652F50Db5B7a3E753Db5c1730c7460936BE67Ce;
address private presaleContract = 0xA74855652777aFB6Cf8b10a44c85d687b1D19d28;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
constructor() {
_issue(ownerAddress, 500000000000000000000);
_issue(presaleContract, 1500000000000000000000);
}
function name() public pure returns(string memory) {
return _name;
}
function symbol() public pure returns(string memory) {
return _symbol;
}
function decimals() public pure returns(uint8) {
return _decimals;
}
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address owner) public view returns (uint256) {
return _balances[owner];
}
function allowance(address owner, address spender) public view returns (uint256) {
return _allowed[owner][spender];
}
function slash(uint256 value) public pure returns (uint256) {
uint256 roundValue = value.ceil(basePercent);
uint256 slashValue = roundValue.mul(basePercent).div(10000); //Burn
return slashValue;
}
function transfer(address to, uint256 value) public returns (bool) {
require(value <= _balances[msg.sender]);
uint256 tokensToBurn = slash(value); // Burn on transfer
uint256 tokensToTransfer = value.sub(tokensToBurn);
_balances[msg.sender] = _balances[msg.sender].sub(value);
_balances[to] = _balances[to].add(tokensToTransfer);
_totalSupply = _totalSupply.sub(tokensToBurn);
emit Transfer(msg.sender, to, tokensToTransfer);
emit Transfer(msg.sender, address(0), tokensToBurn);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
require(spender != address(0));
_allowed[msg.sender][spender] = (
_allowed[msg.sender][spender].add(addedValue));
emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
require(spender != address(0));
_allowed[msg.sender][spender] = (
_allowed[msg.sender][spender].sub(subtractedValue));
emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
return true;
}
function _transfer(address from, address to, uint256 value) internal {
_balances[from] = _balances[from].sub(value);
_balances[to] = _balances[to].add(value);
emit Transfer(from, to, value);
}
function approve(address spender, uint256 value) public returns (bool) {
require(spender != address(0));
_allowed[msg.sender][spender] = value;
emit Approval(msg.sender, spender, value);
return true;
}
function transferFrom(address from, address to, uint256 value) public returns (bool) {
require(value <= _balances[from]);
require(value <= _allowed[from][msg.sender]);
require(to != address(0));
_balances[from] = _balances[from].sub(value);
uint256 tokensToBurn = slash(value); //Burn on transfer
uint256 tokensToTransfer = value.sub(tokensToBurn);
_balances[to] = _balances[to].add(tokensToTransfer);
_totalSupply = _totalSupply.sub(tokensToBurn);
_allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value);
emit Transfer(from, to, tokensToTransfer);
emit Transfer(from, address(0), tokensToBurn);
return true;
}
function _issue(address account, uint256 amount) internal {
require(amount != 0);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
function burn(uint256 amount) external {
_burn(msg.sender, amount);
}
function _burn(address account, uint256 amount) internal {
require(amount != 0);
require(amount <= _balances[account]);
_totalSupply = _totalSupply.sub(amount);
_balances[account] = _balances[account].sub(amount);
emit Transfer(account, address(0), amount);
}
function burnFrom(address account, uint256 amount) external {
require(amount <= _allowed[account][msg.sender]);
_allowed[account][msg.sender] = _allowed[account][msg.sender].sub(amount);
_burn(account, amount);
}
function _mint(address account, uint256 value) internal {
_balances[account] = _balances[account].add(value);
emit Transfer(address(0), account, value);
}
fallback() external payable {
revert();
}
receive() external payable {
revert();
}
}
PreSale Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Lib] SafeMath
- [Int] mul
- [Int] add
+ Ownable
- [Pub] #
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ yLEAFsale (Ownable)
- [Pub] #
- [Pub] startSale #
- modifiers: onlyOwner
- [Pub] isActive
- [Pub] goalReached
- [Ext] ($)
- [Ext] ($)
- [Pub] buyTokens ($)
- modifiers: whenSaleIsActive
- [Pub] tokensAvailable
- [Pub] endSale #
- modifiers: onlyOwner
Click here to download the source code as a .sol file.
//SPDX-License-Identifier: MIT
/*##################################################
* ############ yLEAF Token Sale ##################
* ##################################################
*
* ##################################################
* ############# 20 November 2020 ###################
* ##################################################
**/
pragma solidity >=0.6.0 <0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
pragma solidity ^0.7.5;
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
contract Ownable {
address public owner;
address payable public ownerPayable;
constructor() {
owner = address(msg.sender);
ownerPayable = address(uint160(owner));
}
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0));
owner = newOwner;
ownerPayable = address(uint160(owner));
}
}
contract yLEAFsale is Ownable {
using SafeMath for uint256;
IERC20 token;
string public constant Info = "This is the official Presale contract for yLEAF";
uint256 public constant RATE = 7; //number of tokens per ether
uint256 public constant CAP = 200; //Number of ether accepted until the sale ends
bool private initialized = false; //We dont start until you call startSale()
uint256 public raisedAmount = 0; //allow users to read the amount of funds raised
modifier whenSaleIsActive() {
// Check if sale is active
assert(isActive());
_;
}
constructor() {}
function startSale(address _tokenAddr) public onlyOwner {
require(initialized == false); //Call when you are ready to start the sale
token = IERC20(_tokenAddr);
token.approve(address(this), 115792089237316195423570985008687907853269984665640564039457584007913129639935);
initialized = true;
}
function isActive() public view returns (bool) {
return (
initialized == true //Lets the public know if we're live
);
}
function goalReached() public view returns (bool) {
return (raisedAmount >= CAP * 1 ether);
}
fallback() external payable {
buyTokens();
} //Fallbacks so if someone sends ether directly to the contract it will function as a purchase
receive() external payable {
buyTokens();
}
function buyTokens() public payable whenSaleIsActive {
require(msg.value >= 0.5 ether);
require(msg.value <= 2 ether);
uint256 weiAmount = msg.value;
uint256 tokens = weiAmount.mul(RATE);
raisedAmount = raisedAmount.add(msg.value);
ownerPayable.transfer(msg.value);
token.transferFrom(address(this), msg.sender, tokens);
}
function tokensAvailable() public view returns (uint256) {
return token.balanceOf(address(this));
}
function endSale() onlyOwner public {
uint256 tokenBalance = token.balanceOf(address(this));
token.transferFrom(address(this), owner, tokenBalance); //Tokens returned to owner wallet
selfdestruct(ownerPayable);
}
}