{"id":15822054,"url":"https://github.com/sambacha/yacademy-content","last_synced_at":"2026-04-30T01:36:56.289Z","repository":{"id":54960032,"uuid":"325788865","full_name":"sambacha/yacademy-content","owner":"sambacha","description":"easy content for yAcademy ","archived":false,"fork":false,"pushed_at":"2021-01-19T16:09:55.000Z","size":5836,"stargazers_count":0,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-11T01:57:39.749Z","etag":null,"topics":["best-practices","ethereum","gitcoin","security","solidity","yacademy"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sambacha.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-12-31T11:46:32.000Z","updated_at":"2020-12-31T11:48:01.000Z","dependencies_parsed_at":"2022-08-14T07:30:38.639Z","dependency_job_id":null,"html_url":"https://github.com/sambacha/yacademy-content","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sambacha/yacademy-content","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sambacha%2Fyacademy-content","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sambacha%2Fyacademy-content/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sambacha%2Fyacademy-content/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sambacha%2Fyacademy-content/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sambacha","download_url":"https://codeload.github.com/sambacha/yacademy-content/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sambacha%2Fyacademy-content/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32451475,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T22:27:22.272Z","status":"ssl_error","status_checked_at":"2026-04-29T22:10:49.234Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["best-practices","ethereum","gitcoin","security","solidity","yacademy"],"created_at":"2024-10-05T08:00:28.033Z","updated_at":"2026-04-30T01:36:56.273Z","avatar_url":"https://github.com/sambacha.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# YAcademy Quick Examples\n\n- [YAcademy Quick Examples](#yacademy-quick-examples)\n- [Incorrect interface](#incorrect-interface)\n  - [Alice.sol](#alicesol)\n  - [Bob.sol](#bobsol)\n- [Incorrect interface](#incorrect-interface-1)\n  - [Attack Scenario](#attack-scenario)\n  - [Mitigations](#mitigations)\n  - [Example](#example)\n- [Race Condition](#race-condition)\n  - [Contract.sol](#contractsol)\n- [Race Condition](#race-condition-1)\n  - [Attack Scenario](#attack-scenario-1)\n  - [Mitigations](#mitigations-1)\n- [Unchecked External Call](#unchecked-external-call)\n  - [KingOfTheEtherThrone.sol](#kingoftheetherthronesol)\n  - [Attack](#attack)\n  - [Mitigation](#mitigation)\n  - [Example](#example-1)\n  - [References](#references)\n- [Forced Ether Reception](#forced-ether-reception)\n  - [Coin.sol](#coinsol)\n- [Contracts can be forced to receive ether](#contracts-can-be-forced-to-receive-ether)\n  - [Attack Scenario](#attack-scenario-2)\n  - [Example](#example-2)\n  - [Mitigations](#mitigations-2)\n  - [References](#references-1)\n- [Unprotected function](#unprotected-function)\n  - [Unprotected.sol](#unprotectedsol)\n- [Unprotected function](#unprotected-function-1)\n  - [Attack Scenario](#attack-scenario-3)\n  - [Mitigations](#mitigations-3)\n  - [Examples](#examples)\n\n# Incorrect interface\n\n## Alice.sol\n\n```js\ncontract Alice {\n    int public val;\n\n    function set(int new_val){\n        val = new_val;\n    }\n\n    function set_fixed(int new_val){\n        val = new_val;\n    }\n\n    function(){\n        val = 1;\n    }\n}\n```\n\n## Bob.sol\n\n```js\nabstract contract Alice {\n    function set(uint) public virtual;\n    function set_fixed(int) public virtual;\n}\n\ncontract Bob {\n    function set(Alice c) public{\n        c.set(42);\n    }\n\n    function set_fixed(Alice c) public{\n        c.set_fixed(42);\n    }\n}\n```\n\n# Incorrect interface\n\nA contract interface defines functions with a different type signature than the implementation, causing two different method id's to be created.\nAs a result, when the interfact is called, the fallback method will be executed.\n\n## Attack Scenario\n\n- The interface is incorrectly defined. `Alice.set(uint)` takes an `uint` in `Bob.sol` but `Alice.set(int)` a `int` in `Alice.sol`. The two interfaces will produce two differents method IDs. As a result, Bob will call the fallback function of Alice rather than of `set`.\n\n## Mitigations\n\nVerify that type signatures are identical between inferfaces and implementations.\n\n## Example\n\nWe now walk through how to find this vulnerability in the [Alice](#Alice.sol) and [Bob](#Bob.sol) contracts in this repo.\n\nFirst, get the bytecode and the abi of the contracts:\n\n```̀bash\n$ solc --bin Alice.sol\n6060604052341561000f57600080fd5b5b6101158061001f6000396000f300606060405236156051576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633c6bb436146067578063a5d5e46514608d578063e5c19b2d1460ad575b3415605b57600080fd5b5b60016000819055505b005b3415607157600080fd5b607760cd565b6040518082815260200191505060405180910390f35b3415609757600080fd5b60ab600480803590602001909190505060d3565b005b341560b757600080fd5b60cb600480803590602001909190505060de565b005b60005481565b806000819055505b50565b806000819055505b505600a165627a7a723058207d0ad6d1ce356adf9fa0284c9f887bb4b912204886b731c37c2ae5d16aef19a20029\n$ solc --abi Alice.sol\n[{\"constant\":true,\"inputs\":[],\"name\":\"val\",\"outputs\":[{\"name\":\"\",\"type\":\"int256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"new_val\",\"type\":\"int256\"}],\"name\":\"set_fixed\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"new_val\",\"type\":\"int256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"payable\":false,\"type\":\"fallback\"}]\n\n\n$ solc --bin Bob.sol\n6060604052341561000f57600080fd5b5b6101f58061001f6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632801617e1461004957806390b2290e14610082575b600080fd5b341561005457600080fd5b610080600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506100bb565b005b341561008d57600080fd5b6100b9600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610142565b005b8073ffffffffffffffffffffffffffffffffffffffff166360fe47b1602a6040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b151561012a57600080fd5b6102c65a03f1151561013b57600080fd5b5050505b50565b8073ffffffffffffffffffffffffffffffffffffffff1663a5d5e465602a6040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b15156101b157600080fd5b6102c65a03f115156101c257600080fd5b5050505b505600a165627a7a72305820f8c9dcade78d92097c18627223a8583507e9331ef1e5de02640ffc2e731111320029\n$ solc --abi Bob.sol\n[{\"constant\":false,\"inputs\":[{\"name\":\"c\",\"type\":\"address\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"c\",\"type\":\"address\"}],\"name\":\"set_fixed\",\"outputs\":[],\"payable\":false,\"type\":\"function\"}]\n```\n\nThe following commands were tested on a private blockchain\n\n```javascript\n$ get attach\n\n// this unlock the account for a limited amount of time\n// if you have an error:\n// Error: authentication needed: password or unlock\n// you can to call unlockAccount again\npersonal.unlockAccount(eth.accounts[0], \"apasswordtochange\")\n\nvar bytecodeAlice = '0x6060604052341561000f57600080fd5b5b6101158061001f6000396000f300606060405236156051576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633c6bb436146067578063a5d5e46514608d578063e5c19b2d1460ad575b3415605b57600080fd5b5b60016000819055505b005b3415607157600080fd5b607760cd565b6040518082815260200191505060405180910390f35b3415609757600080fd5b60ab600480803590602001909190505060d3565b005b341560b757600080fd5b60cb600480803590602001909190505060de565b005b60005481565b806000819055505b50565b806000819055505b505600a165627a7a723058207d0ad6d1ce356adf9fa0284c9f887bb4b912204886b731c37c2ae5d16aef19a20029'\nvar abiAlice = [{\"constant\":true,\"inputs\":[],\"name\":\"val\",\"outputs\":[{\"name\":\"\",\"type\":\"int256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"new_val\",\"type\":\"int256\"}],\"name\":\"set_fixed\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"new_val\",\"type\":\"int256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"payable\":false,\"type\":\"fallback\"}]\n\nvar bytecodeBob = '0x6060604052341561000f57600080fd5b5b6101f58061001f6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632801617e1461004957806390b2290e14610082575b600080fd5b341561005457600080fd5b610080600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506100bb565b005b341561008d57600080fd5b6100b9600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610142565b005b8073ffffffffffffffffffffffffffffffffffffffff166360fe47b1602a6040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b151561012a57600080fd5b6102c65a03f1151561013b57600080fd5b5050505b50565b8073ffffffffffffffffffffffffffffffffffffffff1663a5d5e465602a6040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b15156101b157600080fd5b6102c65a03f115156101c257600080fd5b5050505b505600a165627a7a72305820f8c9dcade78d92097c18627223a8583507e9331ef1e5de02640ffc2e731111320029'\nvar abiBob = [{\"constant\":false,\"inputs\":[{\"name\":\"c\",\"type\":\"address\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"c\",\"type\":\"address\"}],\"name\":\"set_fixed\",\"outputs\":[],\"payable\":false,\"type\":\"function\"}]\n\nvar contractAlice = eth.contract(abiAlice);\nvar txDeployAlice = {from:eth.coinbase, data: bytecodeAlice, gas: 1000000};\nvar contractPartialInstanceAlice = contractAlice.new(txDeployAlice);\n\n// Wait to mine the block containing the transaction\n\nvar alice = contractAlice.at(contractPartialInstanceAlice.address);\n\nvar contractBob = eth.contract(abiBob);\nvar txDeployBob = {from:eth.coinbase, data: bytecodeBob, gas: 1000000};\nvar contractPartialInstanceBob = contractBob.new(txDeployBob);\n\n// Wait to mine the block containing the transaction\n\nvar bob = contractBob.at(contractPartialInstanceBob.address);\n\n// From now, wait for each transaction to be mined before calling\n// the others transactions\n\n// print the default value of val: 0\nalice.val()\n\n// call bob.set, as the interface is wrong, it will call\n// the fallback function of alice\nbob.set(alice.address, {from: eth.accounts[0]} )\n// print val: 1\nalice.val()\n\n// call the fixed version of the interface\nbob.set_fixed(alice.address, {from: eth.accounts[0]} )\n// print val: 42\nalice.val()\n```\n\n# Race Condition\n\n## Contract.sol\n\n```js\ninterface ERC20 {\n    function totalSupply() external  returns (uint);\n    function balanceOf(address _owner) external  returns (uint);\n    function transfer(address _to, uint _value) external  returns (bool);\n    function transferFrom(address _from, address _to, uint _value) external  returns (bool);\n    function approve(address _spender, uint _value) external  returns (bool);\n    function allowance(address _owner, address _spender) external  returns (uint);\n    event Transfer(address indexed _from, address indexed _to, uint _value);\n    event Approval(address indexed _owner, address indexed _spender, uint _value);\n}\n\ncontract RaceCondition{\n    address private owner;\n    uint public price;\n    ERC20 token;\n\n    constructor(uint _price, ERC20 _token)\n        public\n    {\n        owner = msg.sender;\n        price = _price;\n        token = _token;\n    }\n\n    // If the owner sees someone calls buy\n    // he can call changePrice to set a new price\n    // If his transaction is mined first, he can\n    // receive more tokens than excepted by the new buyer\n    function buy(uint new_price) payable\n        public\n    {\n        require(msg.value \u003e= price);\n\n        // we assume that the RaceCondition contract\n        // has enough allowance\n        token.transferFrom(msg.sender, owner, price);\n\n        price = new_price;\n        owner = msg.sender;\n    }\n\n    function changePrice(uint new_price) public{\n        require(msg.sender == owner);\n        price = new_price;\n    }\n\n}\n```\n\n# Race Condition\n\nThere is a gap between the creation of a transaction and the moment it is accepted in the blockchain.\nTherefore, an attacker can take advantage of this gap to put a contract in a state that advantages them.\n\n## Attack Scenario\n\n- Bob creates `RaceCondition(100, token)`. Alice trusts `RaceCondition` with all its tokens. Alice calls `buy(150)`\n  Bob sees the transaction, and calls `changePrice(300)`. The transaction of Bob is mined before the one of Alice and\n  as a result, Bob received 300 tokens.\n\n- The ERC20 standard's `approve` and `transferFrom` functions are vulnerable to a race condition. Suppose Alice has\n  approved Bob to spend 100 tokens on her behalf. She then decides to only approve him for 50 tokens and sends\n  a second `approve` transaction. However, Bob sees that he's about to be downgraded and quickly submits a\n  `transferFrom` for the original 100 tokens he was approved for. If this transaction gets mined before Alice's\n  second `approve`, Bob will be able to spend 150 of Alice's tokens.\n\n## Mitigations\n\n- For the ERC20 bug, insist that Alice only be able to `approve` Bob when he is approved for 0 tokens.\n- Keep in mind that all transactions may be front-run\n\n# Unchecked External Call\n\n## KingOfTheEtherThrone.sol\n\n```js\n// A chain-game contract that maintains a 'throne' which agents may pay to rule.\n// See www.kingoftheether.com \u0026 https://github.com/kieranelby/KingOfTheEtherThrone .\n// (c) Kieran Elby 2016. All rights reserved.\n// v0.4.0.\n// Inspired by ethereumpyramid.com and the (now-gone?) \"magnificent bitcoin gem\".\n\n// This contract lives on the blockchain at 0xb336a86e2feb1e87a328fcb7dd4d04de3df254d0\n// and was compiled (using optimization) with:\n// Solidity version: 0.2.1-fad2d4df/.-Emscripten/clang/int linked to libethereum\n\n// For future versions it would be nice to ...\n// TODO - enforce time-limit on reign (can contracts do that without external action)?\n// TODO - add a random reset?\n// TODO - add bitcoin bridge so agents can pay in bitcoin?\n// TODO - maybe allow different return payment address?\n\ncontract KingOfTheEtherThrone {\n\n    struct Monarch {\n        // Address to which their compensation will be sent.\n        address etherAddress;\n        // A name by which they wish to be known.\n        // NB: Unfortunately \"string\" seems to expose some bugs in web3.\n        string name;\n        // How much did they pay to become monarch?\n        uint claimPrice;\n        // When did their rule start (based on block.timestamp)?\n        uint coronationTimestamp;\n    }\n\n    // The wizard is the hidden power behind the throne; they\n    // occupy the throne during gaps in succession and collect fees.\n    address wizardAddress;\n\n    // Used to ensure only the wizard can do some things.\n    modifier onlywizard { if (msg.sender == wizardAddress) _; }\n\n    // How much must the first monarch pay?\n    uint constant startingClaimPrice = 100 finney;\n\n    // The next claimPrice is calculated from the previous claimFee\n    // by multiplying by claimFeeAdjustNum and dividing by claimFeeAdjustDen -\n    // for example, num=3 and den=2 would cause a 50% increase.\n    uint constant claimPriceAdjustNum = 3;\n    uint constant claimPriceAdjustDen = 2;\n\n    // How much of each claimFee goes to the wizard (expressed as a fraction)?\n    // e.g. num=1 and den=100 would deduct 1% for the wizard, leaving 99% as\n    // the compensation fee for the usurped monarch.\n    uint constant wizardCommissionFractionNum = 1;\n    uint constant wizardCommissionFractionDen = 100;\n\n    // How much must an agent pay now to become the monarch?\n    uint public currentClaimPrice;\n\n    // The King (or Queen) of the Ether.\n    Monarch public currentMonarch;\n\n    // Earliest-first list of previous throne holders.\n    Monarch[] public pastMonarchs;\n\n    // Create a new throne, with the creator as wizard and first ruler.\n    // Sets up some hopefully sensible defaults.\n     constructor() public {\n        wizardAddress = msg.sender;\n        currentClaimPrice = startingClaimPrice;\n        currentMonarch = Monarch(\n            wizardAddress,\n            \"[Vacant]\",\n            0,\n            block.timestamp\n        );\n    }\n\n    function numberOfMonarchs() public returns (uint n) {\n        return pastMonarchs.length;\n    }\n\n    // Fired when the throne is claimed.\n    // In theory can be used to help build a front-end.\n    event ThroneClaimed(\n        address usurperEtherAddress,\n        string usurperName,\n        uint newClaimPrice\n    );\n\n    // Fallback function - simple transactions trigger this.\n    // Assume the message data is their desired name.\n    fallback() external {\n        claimThrone(string(msg.data));\n    }\n\n    // Claim the throne for the given name by paying the currentClaimFee.\n    function claimThrone(string memory name) public payable {\n\n        uint valuePaid = msg.value;\n\n        // If they paid too little, reject claim and refund their money.\n        if (valuePaid \u003c currentClaimPrice) {\n            msg.sender.send(valuePaid);\n            return;\n        }\n\n        // If they paid too much, continue with claim but refund the excess.\n        if (valuePaid \u003e currentClaimPrice) {\n            uint excessPaid = valuePaid - currentClaimPrice;\n            msg.sender.send(excessPaid);\n            valuePaid = valuePaid - excessPaid;\n        }\n\n        // The claim price payment goes to the current monarch as compensation\n        // (with a commission held back for the wizard). We let the wizard's\n        // payments accumulate to avoid wasting gas sending small fees.\n\n        uint wizardCommission = (valuePaid * wizardCommissionFractionNum) / wizardCommissionFractionDen;\n\n        uint compensation = valuePaid - wizardCommission;\n\n        if (currentMonarch.etherAddress != wizardAddress) {\n            payable(currentMonarch.etherAddress).send(compensation);\n        } else {\n            // When the throne is vacant, the fee accumulates for the wizard.\n        }\n\n        // Usurp the current monarch, replacing them with the new one.\n        pastMonarchs.push(currentMonarch);\n        currentMonarch = Monarch(\n            msg.sender,\n            name,\n            valuePaid,\n            block.timestamp\n        );\n\n        // Increase the claim fee for next time.\n        // Stop number of trailing decimals getting silly - we round it a bit.\n        uint rawNewClaimPrice = currentClaimPrice * claimPriceAdjustNum / claimPriceAdjustDen;\n        if (rawNewClaimPrice \u003c 10 finney) {\n            currentClaimPrice = rawNewClaimPrice;\n        } else if (rawNewClaimPrice \u003c 100 finney) {\n            currentClaimPrice = 100 szabo * (rawNewClaimPrice / 100 szabo);\n        } else if (rawNewClaimPrice \u003c 1 ether) {\n            currentClaimPrice = 1 finney * (rawNewClaimPrice / 1 finney);\n        } else if (rawNewClaimPrice \u003c 10 ether) {\n            currentClaimPrice = 10 finney * (rawNewClaimPrice / 10 finney);\n        } else if (rawNewClaimPrice \u003c 100 ether) {\n            currentClaimPrice = 100 finney * (rawNewClaimPrice / 100 finney);\n        } else if (rawNewClaimPrice \u003c 1000 ether) {\n            currentClaimPrice = 1 ether * (rawNewClaimPrice / 1 ether);\n        } else if (rawNewClaimPrice \u003c 10000 ether) {\n            currentClaimPrice = 10 ether * (rawNewClaimPrice / 10 ether);\n        } else {\n            currentClaimPrice = rawNewClaimPrice;\n        }\n\n        // Hail the new monarch!\n        emit ThroneClaimed(currentMonarch.etherAddress, currentMonarch.name, currentClaimPrice);\n    }\n\n    // Used only by the wizard to collect his commission.\n    function sweepCommission(uint amount) public onlywizard {\n        payable(wizardAddress).send(amount);\n    }\n\n    // Used only by the wizard to collect his commission.\n    function transferOwnership(address newOwner) public onlywizard {\n        wizardAddress = newOwner;\n    }\n\n}\n```\n\nCertain Solidity operations known as \"external calls\", require the developer to manually ensure that the operation succeeded. This is in contrast to operations which throw an exception on failure. If an external call fails, but is not checked, the contract will continue execution as if the call succeeded. This will likely result in buggy and potentially exploitable behavior from the contract.\n\n## Attack\n\n- A contract uses an unchecked `address.send()` external call to transfer Ether.\n- If it transfers Ether to an attacker contract, the attacker contract can reliably cause the external call to fail, for example, with a fallback function which intentionally runs out of gas.\n- The consequences of this external call failing will be contract specific. - In the case of the King of the Ether contract, this resulted in accidental loss of Ether for some contract users, due to refunds not being sent.\n\n## Mitigation\n\n- Manually perform validation when making external calls\n- Use `address.transfer()`\n\n## Example\n\n- [King of the Ether](https://www.kingoftheether.com/postmortem.html) (line numbers:\n  [100](KotET_source_code/KingOfTheEtherThrone.sol#L100),\n  [107](KotET_source_code/KingOfTheEtherThrone.sol#L107),\n  [120](KotET_source_code/KingOfTheEtherThrone.sol#L120),\n  [161](KotET_source_code/KingOfTheEtherThrone.sol#L161))\n\n## References\n\n- http://solidity.readthedocs.io/en/develop/security-considerations.html\n- http://solidity.readthedocs.io/en/develop/types.html#members-of-addresses\n- https://github.com/ConsenSys/smart-contract-best-practices#handle-errors-in-external-calls\n- https://vessenes.com/ethereum-griefing-wallets-send-w-throw-considered-harmful/\n\n# Forced Ether Reception\n\n## Coin.sol\n\n```js\ncontract owned {\n    address public owner;\n\n     constructor() public {\n        owner = msg.sender;\n    }\n\n    modifier onlyOwner {\n        require(msg.sender == owner);\n        _;\n    }\n\n    function transferOwnership(address newOwner) onlyOwner public {\n        owner = newOwner;\n    }\n}\n\ninterface tokenRecipient {\n    function receiveApproval(address _from, uint256 _value, address _token, bytes calldata _extraData) external; }\n\ncontract TokenERC20 {\n    // Public variables of the token\n    string public name;\n    string public symbol;\n    uint8 public decimals = 18;\n    // 18 decimals is the strongly suggested default, avoid changing it\n    uint256 public totalSupply;\n\n    // This creates an array with all balances\n    mapping (address =\u003e uint256) public balanceOf;\n    mapping (address =\u003e mapping (address =\u003e uint256)) public allowance;\n\n    // This generates a public event on the blockchain that will notify clients\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    // This generates a public event on the blockchain that will notify clients\n    event Approval(address indexed _owner, address indexed _spender, uint256 _value);\n\n    /**\n     * Constrctor function\n     *\n     * Initializes contract with initial supply tokens to the creator of the contract\n     */\n    constructor(\n        string memory tokenName,\n        string memory tokenSymbol\n    ) public {\n        name = tokenName;                                   // Set the name for display purposes\n        symbol = tokenSymbol;                               // Set the symbol for display purposes\n    }\n\n    /**\n     * Internal transfer, only can be called by this contract\n     */\n    function _transfer(address _from, address _to, uint _value) internal virtual {\n        // Prevent transfer to 0x0 address.\n        require(_to != address(0));\n        // Check if the sender has enough\n        require(balanceOf[_from] \u003e= _value);\n        // Check for overflows\n        require(balanceOf[_to] + _value \u003e balanceOf[_to]);\n        // Save this for an assertion in the future\n        uint previousBalances = balanceOf[_from] + balanceOf[_to];\n        // Subtract from the sender\n        balanceOf[_from] -= _value;\n        // Add the same to the recipient\n        balanceOf[_to] += _value;\n        emit Transfer(_from, _to, _value);\n        // Asserts are used to use static analysis to find bugs in your code. They should never fail\n        assert(balanceOf[_from] + balanceOf[_to] == previousBalances);\n    }\n\n    /**\n     * Transfer tokens\n     *\n     * Send `_value` tokens to `_to` from your account\n     *\n     * @param _to The address of the recipient\n     * @param _value the amount to send\n     */\n    function transfer(address _to, uint256 _value) public returns (bool success) {\n        _transfer(msg.sender, _to, _value);\n        return true;\n    }\n\n    /**\n     * Transfer tokens from other address\n     *\n     * Send `_value` tokens to `_to` in behalf of `_from`\n     *\n     * @param _from The address of the sender\n     * @param _to The address of the recipient\n     * @param _value the amount to send\n     */\n    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {\n        require(_value \u003c= allowance[_from][msg.sender]);     // Check allowance\n        allowance[_from][msg.sender] -= _value;\n        _transfer(_from, _to, _value);\n        return true;\n    }\n\n    /**\n     * Set allowance for other address\n     *\n     * Allows `_spender` to spend no more than `_value` tokens in your behalf\n     *\n     * @param _spender The address authorized to spend\n     * @param _value the max amount they can spend\n     */\n    function approve(address _spender, uint256 _value) public\n        returns (bool success) {\n        allowance[msg.sender][_spender] = _value;\n        emit Approval(msg.sender, _spender, _value);\n        return true;\n    }\n\n    /**\n     * Set allowance for other address and notify\n     *\n     * Allows `_spender` to spend no more than `_value` tokens in your behalf, and then ping the contract about it\n     *\n     * @param _spender The address authorized to spend\n     * @param _value the max amount they can spend\n     * @param _extraData some extra information to send to the approved contract\n     */\n    function approveAndCall(address _spender, uint256 _value, bytes memory _extraData)\n        public\n        returns (bool success) {\n        tokenRecipient spender = tokenRecipient(_spender);\n        if (approve(_spender, _value)) {\n            spender.receiveApproval(msg.sender, _value, address(this), _extraData);\n            return true;\n        }\n    }\n\n}\n\n/******************************************/\n/*       ADVANCED TOKEN STARTS HERE       */\n/******************************************/\n\ncontract MyAdvancedToken is owned, TokenERC20 {\n\n    mapping (address =\u003e bool) public frozenAccount;\n\n    /* This generates a public event on the blockchain that will notify clients */\n    event FrozenFunds(address target, bool frozen);\n\n    /* Initializes contract with initial supply tokens to the creator of the contract */\n    constructor(\n        string memory tokenName,\n        string memory tokenSymbol\n    ) TokenERC20(tokenName, tokenSymbol) public {}\n\n    /* Internal transfer, only can be called by this contract */\n    function _transfer(address _from, address _to, uint _value) internal override{\n        require (_to != address(0));                               // Prevent transfer to 0x0 address.\n        require (balanceOf[_from] \u003e= _value);               // Check if the sender has enough\n        require (balanceOf[_to] + _value \u003e= balanceOf[_to]); // Check for overflows\n        require(!frozenAccount[_from]);                     // Check if sender is frozen\n        require(!frozenAccount[_to]);                       // Check if recipient is frozen\n        balanceOf[_from] -= _value;                         // Subtract from the sender\n        balanceOf[_to] += _value;                           // Add the same to the recipient\n        emit Transfer(_from, _to, _value);\n    }\n\n    /// @notice Buy tokens from contract by sending ether\n    function buy() payable public {\n        uint amount = msg.value;                          // calculates the amount\n\tbalanceOf[msg.sender] += amount;                  // updates the balance\n        totalSupply += amount;                            // updates the total supply\n        _transfer(address(0x0), msg.sender, amount);      // makes the transfer\n    }\n\n    /* Migration function */\n    function migrate_and_destroy() public onlyOwner {\n\tassert(address(this).balance == totalSupply);                 // consistency check\n\tselfdestruct(payable(owner));                                      // transfer the ether to the owner and kill the contract\n    }\n}\n```\n\n# Contracts can be forced to receive ether\n\nIn certain circunstances, contracts can be forced to receive ether without triggering any code. This should be considered by the contract developers in order to avoid breaking important invariants in their code.\n\n## Attack Scenario\n\nAn attacker can use a specially crafted contract to forceful send ether using `suicide` / `selfdestruct`:\n\n```solidity\ncontract Sender {\n  function receive_and_suicide(address target) payable {\n    suicide(target);\n  }\n}\n```\n\n## Example\n\n- The MyAdvancedToken contract in [coin.sol](coin.sol#L145) is vulnerable to this attack. It will stop the owner to perform the migration of the contract.\n\n## Mitigations\n\nThere is no way to block the reception of ether. The only mitigation is to avoid assuming how the balance of the contract\nincreases and implement checks to handle this type of edge cases.\n\n## References\n\n- https://solidity.readthedocs.io/en/develop/security-considerations.html#sending-and-receiving-ether\n\n# Unprotected function\n\n## Unprotected.sol\n\n```js\ncontract Unprotected{\n    address private owner;\n\n    modifier onlyowner {\n        require(msg.sender==owner);\n        _;\n    }\n\n    constructor()\n        public\n    {\n        owner = msg.sender;\n    }\n\n    // This function should be protected\n    function changeOwner(address _newOwner)\n        public\n    {\n       owner = _newOwner;\n    }\n\n    function changeOwner_fixed(address _newOwner)\n        public\n        onlyowner\n    {\n       owner = _newOwner;\n    }\n}\n```\n\n# Unprotected function\n\nMissing (or incorrectly used) modifier on a function allows an attacker to use sensitive functionality in the contract.\n\n## Attack Scenario\n\nA contract with a `changeOwner` function does not label it as `private` and therefore\nallows anyone to become the contract owner.\n\n## Mitigations\n\nAlways specify a modifier for functions.\n\n## Examples\n\n- An `onlyOwner` modifier is [defined but not used](#Unprotected.sol), allowing anyone to become the `owner`\n- April 2016: [Rubixi allows anyone to become owner](https://etherscan.io/address/0xe82719202e5965Cf5D9B6673B7503a3b92DE20be#code)\n- July 2017: [Parity Wallet](https://blog.zeppelin.solutions/on-the-parity-wallet-multisig-hack-405a8c12e8f7). For code, see [initWallet](WalletLibrary_source_code/WalletLibrary.sol)\n- BitGo Wallet v2 allows anyone to call tryInsertSequenceId. If you try close to MAXINT, no further transactions would be allowed. [Fix: make tryInsertSequenceId private.](https://github.com/BitGo/eth-multisig-v2/commit/8042188f08c879e06f097ae55c140e0aa7baaff8#diff-b498cc6fd64f83803c260abd8de0a8f5)\n- Feb 2020: [Nexus Mutual's Oraclize callback was unprotected—allowing anyone to call it.](https://medium.com/nexus-mutual/responsible-vulnerability-disclosure-ece3fe3bcefa) Oraclize triggers a rebalance to occur via Uniswap.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsambacha%2Fyacademy-content","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsambacha%2Fyacademy-content","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsambacha%2Fyacademy-content/lists"}