Skip to content

Instantly share code, notes, and snippets.

@Tanapruk
Last active July 17, 2018 09:21
Show Gist options
  • Save Tanapruk/eed224e152d7913ca70fbaa8aadd139d to your computer and use it in GitHub Desktop.
Save Tanapruk/eed224e152d7913ca70fbaa8aadd139d to your computer and use it in GitHub Desktop.
  • approve() is to give accountB an amount of token
  • allowance() is for checking the approved amount. You have to specify relationship between accountA and accountB
  • transferFrom() is to transfer the allowed amount
pragma solidity ^0.4.18;
// ----------------------------------------------------------------------------
// 'Tanapruk' token contract
//
// Deployed to : 0xAe53EeAd0eE4c28FA838dAc87Cd6c0D9749Fb829
// Symbol : TANAP
// Name : TANAP Token
// Total supply: 100000000
// Decimals : 18
//
// Enjoy.
//
// (c) by Moritz Neto with BokkyPooBah / Bok Consulting Pty Ltd Au 2017. The MIT Licence.
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// Safe maths
// ----------------------------------------------------------------------------
contract SafeMath {
function safeAdd(uint a, uint b) public pure returns (uint c) {
c = a + b;
require(c >= a);
}
function safeSub(uint a, uint b) public pure returns (uint c) {
require(b <= a);
c = a - b;
}
function safeMul(uint a, uint b) public pure returns (uint c) {
c = a * b;
require(a == 0 || c / a == b);
}
function safeDiv(uint a, uint b) public pure returns (uint c) {
require(b > 0);
c = a / b;
}
}
// ----------------------------------------------------------------------------
// ERC Token Standard #20 Interface
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
// ----------------------------------------------------------------------------
contract ERC20Interface {
function totalSupply() public view returns (uint);
function balanceOf(address tokenOwner) public view returns (uint balance);
function allowance(address tokenOwner, address spender) public view returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);
event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
// ----------------------------------------------------------------------------
// Contract function to receive approval and execute function in one call
//
// Borrowed from MiniMeToken
// ----------------------------------------------------------------------------
contract ApproveAndCallFallBack {
function receiveApproval(address from, uint256 tokens, address token, bytes data) public;
}
// ----------------------------------------------------------------------------
// Owned contract
// ----------------------------------------------------------------------------
contract Owned {
address public owner;
address public newOwner;
event OwnershipTransferred(address indexed _from, address indexed _to);
constructor() public {
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function transferOwnership(address _newOwner) public onlyOwner {
newOwner = _newOwner;
}
function acceptOwnership() public {
require(msg.sender == newOwner);
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
newOwner = address(0);
}
}
// ----------------------------------------------------------------------------
// ERC20 Token, with the addition of symbol, name and decimals and assisted
// token transfers
// ----------------------------------------------------------------------------
contract TanapToken is ERC20Interface, Owned, SafeMath {
string public symbol;
string public name;
uint8 public decimals;
uint public _totalSupply;
mapping(address => uint) balances;
mapping(address => mapping(address => uint)) allowed;
// ------------------------------------------------------------------------
// Constructor
// ------------------------------------------------------------------------
constructor() public {
symbol = "TANAP";
name = "TANAP Token";
decimals = 18;
_totalSupply = 100000000000000000000000000;
balances[0xAe53EeAd0eE4c28FA838dAc87Cd6c0D9749Fb829] = _totalSupply;
emit Transfer(address(0), 0xAe53EeAd0eE4c28FA838dAc87Cd6c0D9749Fb829, _totalSupply);
}
// ------------------------------------------------------------------------
// Total supply
// ------------------------------------------------------------------------
function totalSupply() public view returns (uint) {
return _totalSupply - balances[address(0)];
}
// ------------------------------------------------------------------------
// Get the token balance for account tokenOwner
// ------------------------------------------------------------------------
function balanceOf(address tokenOwner) public view returns (uint balance) {
return balances[tokenOwner];
}
// ------------------------------------------------------------------------
// Transfer the balance from token owner's account to to account
// - Owner's account must have sufficient balance to transfer
// - 0 value transfers are allowed
// ------------------------------------------------------------------------
function transfer(address to, uint tokens) public returns (bool success) {
balances[msg.sender] = safeSub(balances[msg.sender], tokens);
balances[to] = safeAdd(balances[to], tokens);
emit Transfer(msg.sender, to, tokens);
return true;
}
// ------------------------------------------------------------------------
// Token owner can approve for spender to transferFrom(...) tokens
// from the token owner's account
//
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
// recommends that there are no checks for the approval double-spend attack
// as this should be implemented in user interfaces
// ------------------------------------------------------------------------
function approve(address spender, uint tokens) public returns (bool success) {
allowed[msg.sender][spender] = tokens;
emit Approval(msg.sender, spender, tokens);
return true;
}
// ------------------------------------------------------------------------
// Transfer tokens from the from account to the to account
//
// The calling account must already have sufficient tokens approve(...)-d
// for spending from the from account and
// - From account must have sufficient balance to transfer
// - Spender must have sufficient allowance to transfer
// - 0 value transfers are allowed
// ------------------------------------------------------------------------
function transferFrom(address from, address to, uint tokens) public returns (bool success) {
balances[from] = safeSub(balances[from], tokens);
allowed[from][msg.sender] = safeSub(allowed[from][msg.sender], tokens);
balances[to] = safeAdd(balances[to], tokens);
emit Transfer(from, to, tokens);
return true;
}
// ------------------------------------------------------------------------
// Returns the amount of tokens approved by the owner that can be
// transferred to the spender's account
// ------------------------------------------------------------------------
function allowance(address tokenOwner, address spender) public view returns (uint remaining) {
return allowed[tokenOwner][spender];
}
// ------------------------------------------------------------------------
// Token owner can approve for spender to transferFrom(...) tokens
// from the token owner's account. The spender contract function
// receiveApproval(...) is then executed
// ------------------------------------------------------------------------
function approveAndCall(address spender, uint tokens, bytes data) public returns (bool success) {
allowed[msg.sender][spender] = tokens;
emit Approval(msg.sender, spender, tokens);
ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);
return true;
}
// ------------------------------------------------------------------------
// Don't accept ETH
// ------------------------------------------------------------------------
function () public payable {
revert();
}
// ------------------------------------------------------------------------
// Owner can transfer out any accidentally sent ERC20 tokens
// ------------------------------------------------------------------------
function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) {
return ERC20Interface(tokenAddress).transfer(owner, tokens);
}
}
@Tanapruk
Copy link
Author

Tanapruk commented May 10, 2018

Observations

  • contract creation สำเร็จเป็น การส่ง tokens จะถูก generate เข้า address คนสร้าง
  • ทุกการส่ง token จะส่ง to: contractAddress และเรียก function transfer(_to, _token)
  • ใน contract address จะมี balance ของทุกคนที่ถือ/เคยถือ token ของตัวนี้
  • เช็คผ่าน function balanceOf เช่น
tanapTokenContract = new eth.Contract(abi, '0xd677b4e8ca86b60f125a462919d704aef5a386b5')
tanapTokenContract.methods.balanceOf('0x40fd225142586cb0c26320d2270e0b122350f719').call().then(result => console.log(result))
  • return ที่ได้จาก balanceOf มี 0 ต่อท้าย 18 ตัว

@Tanapruk
Copy link
Author

ถ้าเราใช้ OpenZeppelin โค้ดเราจะสั้นลงไปอีก เหลือแค่ constructor() {} และตัวแปรเล็กน้อยเท่านั้น เพราะ function อื่นๆ ถูก inherit ผ่านจาก openZeppelin แล้ว

และ ปริมาณบรรทัดไม่ได้เพิ่มขึ้น เพราะใช้ class เหมือนกันตอน inherit

@Tanapruk
Copy link
Author

นอกจาก basic ทั่วไป ยังมี features อื่นๆ ที่ถ้าอยากทำเพิ่มก็ is มา และใส่เงื่อนไขเข้าไป
ตัวอย่าง feature
https://medium.com/tokeny/the-8-most-popular-features-of-ico-smart-contracts-eb36929757fd

@Tanapruk
Copy link
Author

Tanapruk commented May 21, 2018

Crowdsales

  • MintedCrowdsale เริ่มจาก 0 และ mint ใหม่ทุกครั้งที่มีคน contribute เข้ามา
  • Crowdsale owner คำถามใน stackExchange crowdsale contract is the owner.

@Tanapruk
Copy link
Author

Tanapruk commented Jun 7, 2018

truffler deployer

  • deployer.deploy(SmarContract.Sol) คือการทำ transaction
  • ถ้า contract นั้นต้องการ parameter ให้แนบไปหลัง deploy( SmartContract.Sol, param0, param1, param2)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment