Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Advanced smart contract

72 views

Published on

This is an tutorial for more in-depth smart contract design for ico and its security issue.

Published in: Engineering
  • Be the first to comment

Advanced smart contract

  1. 1. ADVANCED Presenter: Loc Doan SMART CONTRACT
  2. 2. SECURITY ISSUES ❖ Race Condition ❖ Timestamp Dependence ❖ Integer Overflow and Underflow ❖ DoS with (Unexpected) revert ❖ DoS with Block Gas Limit ❖ Transfer vs Send FROM BUSINESS REQUIREMENTS TO TECHNICAL IMPLEMENTATION (CROWDSALE, TRANCHE SALE, ETC) ❖ Basic Functionality ❖ Basic Functionality for Token ❖ Basic Functionality for Crowdsale Timeline
  3. 3. RACE CONDITION public class Counter { protected long count = 0; public void add(long value){ this.count = this.count + value; } } this.count = 0; A: Reads this.count into a register (0) B: Reads this.count into a register (0) B: Adds value 2 to register B: Writes register value (2) back to memory. this.count now equals 2 A: Adds value 3 to register A: Writes register value (3) back to memory. this.count now equals 3 ❖ Thread A wants to add 2 to this.count. ❖ Thread B wants to add 3 to this.count. ❖ Expected result => 5. ❖ Real results => 3.
  4. 4. REENTRANCY mapping (address => uint) private userBalances; function withdrawBalance() public { uint amountToWithdraw = userBalances[msg.sender]; require(msg.sender.call.value(amountToWithdraw)()); // At this point, the caller's code is executed, and can call withdrawBalance again userBalances[msg.sender] = 0; }
  5. 5. CROSS-FUNCTION RACE CONDITIONS t mapping (address => uint) private userBalances; function transfer(address to, uint amount) { if (userBalances[msg.sender] >= amount) { userBalances[to] += amount; userBalances[msg.sender] -= amount; } } function withdrawBalance() public { uint amountToWithdraw = userBalances[msg.sender]; require(msg.sender.call.value(amountToWithdraw)()); // At this point, the caller's code is executed, and can call transfer() userBalances[msg.sender] = 0; }
  6. 6. CHECKS- EFFECTS-INTERACTIONS 1. Conditions 2. Effects (potentially changing conditions) 3. Interaction You need to not only avoid calling external functions too soon, but also avoid calling functions which call external functions.
  7. 7. MUTEX t function deposit() payable public returns (bool) { require(!lockBalances); lockBalances = true; balances[msg.sender] += msg.value; lockBalances = false; return true; }
  8. 8. MUTEX t contract StateHolder { uint private n; address private lockHolder; function getLock() { require(lockHolder == 0); lockHolder = msg.sender; } function releaseLock() { require(msg.sender == lockHolder); lockHolder = 0; } function set(uint newState) { require(msg.sender == lockHolder); n = newState; } } If you use mutexes to protect against race conditions, you will need to carefully ensure that there are no ways for a lock to be claimed and never released.
  9. 9. TIMESTAMP DEPENDENCE Can be manipulated by the miner Use block.number + average blocktime to estimate
  10. 10. INTEGER OVERFLOW AND UNDERFLOW Beware of small int
  11. 11. DOS WITH BLOCK GAS LIMIT struct Payee { address addr; uint256 value; } Payee[] payees; uint256 nextPayeeIndex; function payOut() { uint256 i = nextPayeeIndex; while (i < payees.length && msg.gas > 200000) { payees[i].addr.send(payees[i].value); i++; } nextPayeeIndex = i; } Don't iterate. If you have, you can divide it into multiple transaction.
  12. 12. DOS WITH (UNEXPECTED) REVERT contract Auction { address currentLeader; uint highestBid; function bid() payable { require(msg.value > highestBid); require(currentLeader.send( highestBid)); // Refund the old leader, if it fails then revert currentLeader = msg.sender; highestBid = msg.value; } } address[] private refundAddresses; mapping (address => uint) public refunds; // bad function refundAll() public { for(uint x; x < refundAddresses.length; x++) { // arbitrary length iteration based on how many addresses participated require(refundAddresses[x].send( refunds[refundAddresses[x]])) // doubly bad, now a single failure on send will hold up all funds } } Solution: pull over push payment: create a refund function.
  13. 13. Transfer vs Send Transfer address x = 0x123; address myAddress = this; if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10); If x is a contract address, its code (more specifically: its fallback function, if present) will be executed together with the transfer call (this is a feature of the EVM and cannot be prevented). If that execution runs out of gas or fails in any way, the Ether transfer will be reverted and the current contract will stop with an exception. Send If the execution fails, the current contract will not stop with an exception, but send will return false. There are some dangers in using send: The transfer fails if the call stack depth is at 1024 (this can always be forced by the caller) and it also fails if the recipient runs out of gas. So in order to make safe Ether transfers, always check the return value of send, use transfer or even better: use a pattern where the recipient withdraws the money.
  14. 14. ❖ Token ❖ Pricing Strategy ❖ Finalize Agent Crowdsale Structure
  15. 15. SAFE MATH OWNABLE HALTABLE Safe unsigned safe math. Provides basic authorization control. Implement an emergency stop mechanism.
  16. 16. BURNABLE TOKEN RELEASABLE TOKEN UPGRADEABLE TOKEN Implement burn functionality for token. It means destroy, or make the token invalid. Allow token to be transfered after the crowdsale. Still give some special case can be transfered Content: Allow to transfer token from a contract to another contract. This "another contract" can have upgraded functionality for the token.
  17. 17. MINTABLE TOKEN CROWDSALE TOKEN Implement mint functionality for token. It means to create new token in the system. A crowdsaled token.
  18. 18. PRICING STRATEGY FLAT PRICING Interface for defining crowdsale pricing. Fixed crowdsale pricing - everybody gets the same price.
  19. 19. MILESTONE PRICING TOKEN TRANCHE PRICING Time milestone based pricing with special support for pre-ico deals. Tranche based pricing with special support for pre-ico deals.
  20. 20. FINALIZE AGENT NULL FINALIZE AGENT DEFAULT FINALIZE AGENT Finalize agent defines what happens at the end of succeseful crowdsale. A finalize agent that does nothing. Token transfer must be manually released by the owner. Unlock tokens.
  21. 21. BONUS FINALIZE AGENT EXTRA FINALIZE AGENT At the end of the successful crowdsale allocate % bonus of tokens to the team. Unlock tokens. At the end of the successful crowdsale allocate % bonus of tokens to the team. Do not unlock the tokens.
  22. 22. CROWDSALEBASE CROWDSALE UNCAPPEDCROWDSALE Implements basic state machine logic, but leaves out all buy functions so that subclasses can implement their own buying logic. Abstract base contract for token sales with the default buy entry points. Handle Does not Handle Intended usage - A short time window - Flat price - No cap
  23. 23. MINTEDETHCAPPE- CROWDSALE MINTEDTOKENCAPPED- CROWDSALE RELAUNCHED- CROWDSALE ICO crowdsale contract that is capped by amount of ETH. Tokens are dynamically created during the crowdsale. ICO crowdsale contract that is capped by amout of tokens. Tokens are dynamically created during the crowdsale. A crowdsale that retains the previous token, but changes some parameters. Investor data can be manually fed in. Mostly useful as a hot fix
  24. 24. Q&A
  25. 25. THANK YOU FOR LISTENING

×