-
-
Save erbrito/e301e8b8ca18f264bef714c50a167d12 to your computer and use it in GitHub Desktop.
| pragma solidity ^0.4.16; | |
| contract owned { | |
| address public owner; | |
| function owned() public { | |
| owner = msg.sender; | |
| } | |
| modifier onlyOwner { | |
| require(msg.sender == owner); | |
| _; | |
| } | |
| function transferOwnership(address newOwner) onlyOwner public { | |
| owner = newOwner; | |
| } | |
| } | |
| contract tokenRecipient { | |
| event receivedEther(address sender, uint amount); | |
| event receivedTokens(address _from, uint256 _value, address _token, bytes _extraData); | |
| function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public { | |
| Token t = Token(_token); | |
| require(t.transferFrom(_from, this, _value)); | |
| receivedTokens(_from, _value, _token, _extraData); | |
| } | |
| function () payable public { | |
| receivedEther(msg.sender, msg.value); | |
| } | |
| } | |
| interface Token { | |
| function transferFrom(address _from, address _to, uint256 _value) public returns (bool success); | |
| } | |
| contract Congress is owned, tokenRecipient { | |
| // Contract Variables and events | |
| uint public minimumQuorum; | |
| uint public debatingPeriodInMinutes; | |
| int public majorityMargin; | |
| Proposal[] public proposals; | |
| uint public numProposals; | |
| mapping (address => uint) public memberId; | |
| Member[] public members; | |
| event ProposalAdded(uint proposalID, address recipient, uint amount, string description); | |
| event Voted(uint proposalID, bool position, address voter, string justification); | |
| event ProposalTallied(uint proposalID, int result, uint quorum, bool active); | |
| event MembershipChanged(address member, bool isMember); | |
| event ChangeOfRules(uint newMinimumQuorum, uint newDebatingPeriodInMinutes, int newMajorityMargin); | |
| struct Proposal { | |
| address recipient; | |
| uint amount; | |
| string description; | |
| uint votingDeadline; | |
| bool executed; | |
| bool proposalPassed; | |
| uint numberOfVotes; | |
| int currentResult; | |
| bytes32 proposalHash; | |
| Vote[] votes; | |
| mapping (address => bool) voted; | |
| } | |
| struct Member { | |
| address member; | |
| string name; | |
| uint memberSince; | |
| } | |
| struct Vote { | |
| bool inSupport; | |
| address voter; | |
| string justification; | |
| } | |
| // Modifier that allows only shareholders to vote and create new proposals | |
| modifier onlyMembers { | |
| require(memberId[msg.sender] != 0); | |
| _; | |
| } | |
| /** | |
| * Constructor function | |
| */ | |
| function Congress ( | |
| uint minimumQuorumForProposals, | |
| uint minutesForDebate, | |
| int marginOfVotesForMajority | |
| ) payable public { | |
| changeVotingRules(minimumQuorumForProposals, minutesForDebate, marginOfVotesForMajority); | |
| // It’s necessary to add an empty first member | |
| addMember(0, ""); | |
| // and let's add the founder, to save a step later | |
| addMember(owner, 'founder'); | |
| } | |
| /** | |
| * Add member | |
| * | |
| * Make `targetMember` a member named `memberName` | |
| * | |
| * @param targetMember ethereum address to be added | |
| * @param memberName public name for that member | |
| */ | |
| function addMember(address targetMember, string memberName) onlyOwner public { | |
| uint id = memberId[targetMember]; | |
| if (id == 0) { | |
| memberId[targetMember] = members.length; | |
| id = members.length++; | |
| } | |
| members[id] = Member({member: targetMember, memberSince: now, name: memberName}); | |
| MembershipChanged(targetMember, true); | |
| } | |
| /** | |
| * Remove member | |
| * | |
| * @notice Remove membership from `targetMember` | |
| * | |
| * @param targetMember ethereum address to be removed | |
| */ | |
| function removeMember(address targetMember) onlyOwner public { | |
| require(memberId[targetMember] != 0); | |
| for (uint i = memberId[targetMember]; i<members.length-1; i++){ | |
| members[i] = members[i+1]; | |
| } | |
| delete members[members.length-1]; | |
| members.length--; | |
| } | |
| /** | |
| * Change voting rules | |
| * | |
| * Make so that proposals need to be discussed for at least `minutesForDebate/60` hours, | |
| * have at least `minimumQuorumForProposals` votes, and have 50% + `marginOfVotesForMajority` votes to be executed | |
| * | |
| * @param minimumQuorumForProposals how many members must vote on a proposal for it to be executed | |
| * @param minutesForDebate the minimum amount of delay between when a proposal is made and when it can be executed | |
| * @param marginOfVotesForMajority the proposal needs to have 50% plus this number | |
| */ | |
| function changeVotingRules( | |
| uint minimumQuorumForProposals, | |
| uint minutesForDebate, | |
| int marginOfVotesForMajority | |
| ) onlyOwner public { | |
| minimumQuorum = minimumQuorumForProposals; | |
| debatingPeriodInMinutes = minutesForDebate; | |
| majorityMargin = marginOfVotesForMajority; | |
| ChangeOfRules(minimumQuorum, debatingPeriodInMinutes, majorityMargin); | |
| } | |
| /** | |
| * Add Proposal | |
| * | |
| * Propose to send `weiAmount / 1e18` ether to `beneficiary` for `jobDescription`. `transactionBytecode ? Contains : Does not contain` code. | |
| * | |
| * @param beneficiary who to send the ether to | |
| * @param weiAmount amount of ether to send, in wei | |
| * @param jobDescription Description of job | |
| * @param transactionBytecode bytecode of transaction | |
| */ | |
| function newProposal( | |
| address beneficiary, | |
| uint weiAmount, | |
| string jobDescription, | |
| bytes transactionBytecode | |
| ) | |
| onlyMembers public | |
| returns (uint proposalID) | |
| { | |
| proposalID = proposals.length++; | |
| Proposal storage p = proposals[proposalID]; | |
| p.recipient = beneficiary; | |
| p.amount = weiAmount; | |
| p.description = jobDescription; | |
| p.proposalHash = keccak256(beneficiary, weiAmount, transactionBytecode); | |
| p.votingDeadline = now + debatingPeriodInMinutes * 1 minutes; | |
| p.executed = false; | |
| p.proposalPassed = false; | |
| p.numberOfVotes = 0; | |
| ProposalAdded(proposalID, beneficiary, weiAmount, jobDescription); | |
| numProposals = proposalID+1; | |
| return proposalID; | |
| } | |
| /** | |
| * Add proposal in Ether | |
| * | |
| * Propose to send `etherAmount` ether to `beneficiary` for `jobDescription`. `transactionBytecode ? Contains : Does not contain` code. | |
| * This is a convenience function to use if the amount to be given is in round number of ether units. | |
| * | |
| * @param beneficiary who to send the ether to | |
| * @param etherAmount amount of ether to send | |
| * @param jobDescription Description of job | |
| * @param transactionBytecode bytecode of transaction | |
| */ | |
| function newProposalInEther( | |
| address beneficiary, | |
| uint etherAmount, | |
| string jobDescription, | |
| bytes transactionBytecode | |
| ) | |
| onlyMembers public | |
| returns (uint proposalID) | |
| { | |
| return newProposal(beneficiary, etherAmount * 1 ether, jobDescription, transactionBytecode); | |
| } | |
| /** | |
| * Check if a proposal code matches | |
| * | |
| * @param proposalNumber ID number of the proposal to query | |
| * @param beneficiary who to send the ether to | |
| * @param weiAmount amount of ether to send | |
| * @param transactionBytecode bytecode of transaction | |
| */ | |
| function checkProposalCode( | |
| uint proposalNumber, | |
| address beneficiary, | |
| uint weiAmount, | |
| bytes transactionBytecode | |
| ) | |
| constant public | |
| returns (bool codeChecksOut) | |
| { | |
| Proposal storage p = proposals[proposalNumber]; | |
| return p.proposalHash == keccak256(beneficiary, weiAmount, transactionBytecode); | |
| } | |
| /** | |
| * Log a vote for a proposal | |
| * | |
| * Vote `supportsProposal? in support of : against` proposal #`proposalNumber` | |
| * | |
| * @param proposalNumber number of proposal | |
| * @param supportsProposal either in favor or against it | |
| * @param justificationText optional justification text | |
| */ | |
| function vote( | |
| uint proposalNumber, | |
| bool supportsProposal, | |
| string justificationText | |
| ) | |
| onlyMembers public | |
| returns (uint voteID) | |
| { | |
| Proposal storage p = proposals[proposalNumber]; // Get the proposal | |
| require(!p.voted[msg.sender]); // If has already voted, cancel | |
| p.voted[msg.sender] = true; // Set this voter as having voted | |
| p.numberOfVotes++; // Increase the number of votes | |
| if (supportsProposal) { // If they support the proposal | |
| p.currentResult++; // Increase score | |
| } else { // If they don't | |
| p.currentResult--; // Decrease the score | |
| } | |
| // Create a log of this event | |
| Voted(proposalNumber, supportsProposal, msg.sender, justificationText); | |
| return p.numberOfVotes; | |
| } | |
| /** | |
| * Finish vote | |
| * | |
| * Count the votes proposal #`proposalNumber` and execute it if approved | |
| * | |
| * @param proposalNumber proposal number | |
| * @param transactionBytecode optional: if the transaction contained a bytecode, you need to send it | |
| */ | |
| function executeProposal(uint proposalNumber, bytes transactionBytecode) public { | |
| Proposal storage p = proposals[proposalNumber]; | |
| require(now > p.votingDeadline // If it is past the voting deadline | |
| && !p.executed // and it has not already been executed | |
| && p.proposalHash == keccak256(p.recipient, p.amount, transactionBytecode) // and the supplied code matches the proposal | |
| && p.numberOfVotes >= minimumQuorum); // and a minimum quorum has been reached... | |
| // ...then execute result | |
| if (p.currentResult > majorityMargin) { | |
| // Proposal passed; execute the transaction | |
| p.executed = true; // Avoid recursive calling | |
| require(p.recipient.call.value(p.amount)(transactionBytecode)); | |
| p.proposalPassed = true; | |
| } else { | |
| // Proposal failed | |
| p.proposalPassed = false; | |
| } | |
| // Fire Events | |
| ProposalTallied(proposalNumber, p.currentResult, p.numberOfVotes, p.proposalPassed); | |
| } | |
| } |
| pragma solidity ^0.4.16; | |
| interface token { | |
| function transfer(address receiver, uint amount); | |
| } | |
| contract Crowdsale { | |
| address public beneficiary; | |
| uint public fundingGoal; | |
| uint public amountRaised; | |
| uint public deadline; | |
| uint public price; | |
| token public tokenReward; | |
| mapping(address => uint256) public balanceOf; | |
| bool fundingGoalReached = false; | |
| bool crowdsaleClosed = false; | |
| event GoalReached(address recipient, uint totalAmountRaised); | |
| event FundTransfer(address backer, uint amount, bool isContribution); | |
| /** | |
| * Constructor function | |
| * | |
| * Setup the owner | |
| */ | |
| function Crowdsale( | |
| address ifSuccessfulSendTo, | |
| uint fundingGoalInEthers, | |
| uint durationInMinutes, | |
| uint etherCostOfEachToken, | |
| address addressOfTokenUsedAsReward | |
| ) { | |
| beneficiary = ifSuccessfulSendTo; | |
| fundingGoal = fundingGoalInEthers * 1 ether; | |
| deadline = now + durationInMinutes * 1 minutes; | |
| price = etherCostOfEachToken * 1 ether; | |
| tokenReward = token(addressOfTokenUsedAsReward); | |
| } | |
| /** | |
| * Fallback function | |
| * | |
| * The function without name is the default function that is called whenever anyone sends funds to a contract | |
| */ | |
| function () payable { | |
| require(!crowdsaleClosed); | |
| uint amount = msg.value; | |
| balanceOf[msg.sender] += amount; | |
| amountRaised += amount; | |
| tokenReward.transfer(msg.sender, amount / price); | |
| FundTransfer(msg.sender, amount, true); | |
| } | |
| modifier afterDeadline() { if (now >= deadline) _; } | |
| /** | |
| * Check if goal was reached | |
| * | |
| * Checks if the goal or time limit has been reached and ends the campaign | |
| */ | |
| function checkGoalReached() afterDeadline { | |
| if (amountRaised >= fundingGoal){ | |
| fundingGoalReached = true; | |
| GoalReached(beneficiary, amountRaised); | |
| } | |
| crowdsaleClosed = true; | |
| } | |
| /** | |
| * Withdraw the funds | |
| * | |
| * Checks to see if goal or time limit has been reached, and if so, and the funding goal was reached, | |
| * sends the entire amount to the beneficiary. If goal was not reached, each contributor can withdraw | |
| * the amount they contributed. | |
| */ | |
| function safeWithdrawal() afterDeadline { | |
| if (!fundingGoalReached) { | |
| uint amount = balanceOf[msg.sender]; | |
| balanceOf[msg.sender] = 0; | |
| if (amount > 0) { | |
| if (msg.sender.send(amount)) { | |
| FundTransfer(msg.sender, amount, false); | |
| } else { | |
| balanceOf[msg.sender] = amount; | |
| } | |
| } | |
| } | |
| if (fundingGoalReached && beneficiary == msg.sender) { | |
| if (beneficiary.send(amountRaised)) { | |
| FundTransfer(beneficiary, amountRaised, false); | |
| } else { | |
| //If we fail to send the funds to beneficiary, unlock funders balance | |
| fundingGoalReached = false; | |
| } | |
| } | |
| } | |
| } |
| # add contract to file ./contracts/ContractName.sol | |
| npm install zeppelin-solidity | |
| --- | |
| pragma solidity ^0.4.17; | |
| import 'zeppelin-solidity/contracts/token/ERC20/StandardToken.sol'; | |
| contract TutorialToken is StandardToken { | |
| --- | |
| truffle compile | |
| vi migrations/2_deploy_contracts.js | |
| ---- | |
| var TokenERC20 = artifacts.require("TokenERC20"); | |
| module.exports = function(deployer) { | |
| deployer.deploy(TokenERC20, 100, "Gadgets", "(:package:)"); | |
| }; | |
| ---- | |
| truffle migrate |
| // bad | |
| if(!someAddress.call.value(100)()) { | |
| // Some failure code | |
| } | |
| // good | |
| if(!someAddress.send(100)) { | |
| // Some failure code | |
| } | |
| // bad | |
| someAddress.send(55); | |
| someAddress.call.value(55)(); // this is doubly dangerous, as it will forward all remaining gas and doesn't check for result | |
| someAddress.call.value(100)(bytes4(sha3("deposit()"))); // if deposit throws an exception, the raw call() will only return false and transaction will NOT be reverted | |
| // good | |
| if(!someAddress.send(55)) { | |
| // Some failure code | |
| } | |
| ExternalContract(someAddress).deposit.value(100); | |
| // bad | |
| contract auction { | |
| address highestBidder; | |
| uint highestBid; | |
| function bid() { | |
| if (msg.value < highestBid) throw; | |
| if (highestBidder != 0) { | |
| if (!highestBidder.send(highestBid)) { // if this call consistently fails, no one else can bid | |
| throw; | |
| } | |
| } | |
| highestBidder = msg.sender; | |
| highestBid = msg.value; | |
| } | |
| } | |
| // good | |
| contract auction { | |
| address highestBidder; | |
| uint highestBid; | |
| mapping(address => uint) refunds; | |
| function bid() external { | |
| if (msg.value < highestBid) throw; | |
| if (highestBidder != 0) { | |
| refunds[highestBidder] += highestBid; // record the refund that this user can claim | |
| } | |
| highestBidder = msg.sender; | |
| highestBid = msg.value; | |
| } | |
| function withdrawRefund() external { | |
| uint refund = refunds[msg.sender]; | |
| refunds[msg.sender] = 0; | |
| if (!msg.sender.send(refund)) { | |
| refunds[msg.sender] = refund; // reverting state because send failed | |
| } | |
| } | |
| } | |
| // bad | |
| Bank.withdraw(100); // Unclear whether trusted or untrusted | |
| function makeWithdrawal(uint amount) { // Isn't clear that this function is potentially unsafe | |
| UntrustedBank.withdraw(amount); | |
| } | |
| // good | |
| UntrustedBank.withdraw(100); // untrusted external call | |
| TrustedBank.withdraw(100); // external but trusted bank contract maintained by XYZ Corp | |
| function makeUntrustedWithdrawal(uint amount) { | |
| UntrustedBank.withdraw(amount); | |
| } | |
| // bad | |
| uint x = 5 / 2; // Result is 2, all integer divison rounds DOWN to the nearest integer | |
| // good | |
| uint multiplier = 10; | |
| uint x = (5 * multiplier) / 2; | |
| uint numerator = 5; | |
| uint denominator = 2; | |
| // bad | |
| function() { balances[msg.sender] += msg.value; } | |
| // good | |
| function() { throw; } | |
| function deposit() external { balances[msg.sender] += msg.value; } | |
| function() { LogDepositReceived(msg.sender); } | |
| // bad | |
| uint x; // the default is private for state variables, but it should be made explicit | |
| function transfer() { // the default is public | |
| // public code | |
| } | |
| // good | |
| uint private y; | |
| function transfer() public { | |
| // public code | |
| } | |
| function internalAction() internal { | |
| // internal code | |
| } | |
| // bad | |
| function divide(uint x, uint y) returns(uint) { | |
| return x / y; | |
| } | |
| // good | |
| function divide(uint x, uint y) returns(uint) { | |
| if (y == 0) { throw; } | |
| return x / y; | |
| } | |
| // bad | |
| event Transfer() {} | |
| function transfer() {} | |
| // good | |
| event LogTransfer() {} | |
| function transfer() external {} | |
| pragma solidity ^0.4.11; | |
| contract StateMachine { | |
| enum Stages { | |
| AcceptingBlindedBids, | |
| RevealBids, | |
| AnotherStage, | |
| AreWeDoneYet, | |
| Finished | |
| } | |
| // This is the current stage. | |
| Stages public stage = Stages.AcceptingBlindedBids; | |
| uint public creationTime = now; | |
| modifier atStage(Stages _stage) { | |
| require(stage == _stage); | |
| _; | |
| } | |
| function nextStage() internal { | |
| stage = Stages(uint(stage) + 1); | |
| } | |
| // Perform timed transitions. Be sure to mention | |
| // this modifier first, otherwise the guards | |
| // will not take the new stage into account. | |
| modifier timedTransitions() { | |
| if (stage == Stages.AcceptingBlindedBids && | |
| now >= creationTime + 10 days) | |
| nextStage(); | |
| if (stage == Stages.RevealBids && | |
| now >= creationTime + 12 days) | |
| nextStage(); | |
| // The other stages transition by transaction | |
| _; | |
| } | |
| // Order of the modifiers matters here! | |
| function bid() | |
| public | |
| payable | |
| timedTransitions | |
| atStage(Stages.AcceptingBlindedBids) | |
| { | |
| // We will not implement that here | |
| } | |
| function reveal() | |
| public | |
| timedTransitions | |
| atStage(Stages.RevealBids) | |
| { | |
| } | |
| // This modifier goes to the next stage | |
| // after the function is done. | |
| modifier transitionNext() | |
| { | |
| _; | |
| nextStage(); | |
| } | |
| function g() | |
| public | |
| timedTransitions | |
| atStage(Stages.AnotherStage) | |
| transitionNext | |
| { | |
| } | |
| function h() | |
| public | |
| timedTransitions | |
| atStage(Stages.AreWeDoneYet) | |
| transitionNext | |
| { | |
| } | |
| function i() | |
| public | |
| timedTransitions | |
| atStage(Stages.Finished) | |
| { | |
| } | |
| } |
| pragma solidity ^0.4.16; | |
| interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) external; } | |
| contract TokenERC20 { | |
| // Public variables of the token | |
| string public name; | |
| string public symbol; | |
| uint8 public decimals = 18; | |
| // 18 decimals is the strongly suggested default, avoid changing it | |
| uint256 public totalSupply; | |
| // This creates an array with all balances | |
| mapping (address => uint256) public balanceOf; | |
| mapping (address => mapping (address => uint256)) public allowance; | |
| // This generates a public event on the blockchain that will notify clients | |
| event Transfer(address indexed from, address indexed to, uint256 value); | |
| // This notifies clients about the amount burnt | |
| event Burn(address indexed from, uint256 value); | |
| /** | |
| * Constructor function | |
| * | |
| * Initializes contract with initial supply tokens to the creator of the contract | |
| */ | |
| function TokenERC20( | |
| uint256 initialSupply, | |
| string tokenName, | |
| string tokenSymbol | |
| ) public { | |
| totalSupply = initialSupply * 10 ** uint256(decimals); // Update total supply with the decimal amount | |
| balanceOf[msg.sender] = totalSupply; // Give the creator all initial tokens | |
| name = tokenName; // Set the name for display purposes | |
| symbol = tokenSymbol; // Set the symbol for display purposes | |
| } | |
| /** | |
| * Internal transfer, only can be called by this contract | |
| */ | |
| function _transfer(address _from, address _to, uint _value) internal { | |
| // Prevent transfer to 0x0 address. Use burn() instead | |
| require(_to != 0x0); | |
| // Check if the sender has enough | |
| require(balanceOf[_from] >= _value); | |
| // Check for overflows | |
| require(balanceOf[_to] + _value >= balanceOf[_to]); | |
| // Save this for an assertion in the future | |
| uint previousBalances = balanceOf[_from] + balanceOf[_to]; | |
| // Subtract from the sender | |
| balanceOf[_from] -= _value; | |
| // Add the same to the recipient | |
| balanceOf[_to] += _value; | |
| emit Transfer(_from, _to, _value); | |
| // Asserts are used to use static analysis to find bugs in your code. They should never fail | |
| assert(balanceOf[_from] + balanceOf[_to] == previousBalances); | |
| } | |
| /** | |
| * Transfer tokens | |
| * | |
| * Send `_value` tokens to `_to` from your account | |
| * | |
| * @param _to The address of the recipient | |
| * @param _value the amount to send | |
| */ | |
| function transfer(address _to, uint256 _value) public { | |
| _transfer(msg.sender, _to, _value); | |
| } | |
| /** | |
| * Transfer tokens from other address | |
| * | |
| * Send `_value` tokens to `_to` on behalf of `_from` | |
| * | |
| * @param _from The address of the sender | |
| * @param _to The address of the recipient | |
| * @param _value the amount to send | |
| */ | |
| function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { | |
| require(_value <= allowance[_from][msg.sender]); // Check allowance | |
| allowance[_from][msg.sender] -= _value; | |
| _transfer(_from, _to, _value); | |
| return true; | |
| } | |
| /** | |
| * Set allowance for other address | |
| * | |
| * Allows `_spender` to spend no more than `_value` tokens on your behalf | |
| * | |
| * @param _spender The address authorized to spend | |
| * @param _value the max amount they can spend | |
| */ | |
| function approve(address _spender, uint256 _value) public | |
| returns (bool success) { | |
| allowance[msg.sender][_spender] = _value; | |
| return true; | |
| } | |
| /** | |
| * Set allowance for other address and notify | |
| * | |
| * Allows `_spender` to spend no more than `_value` tokens on your behalf, and then ping the contract about it | |
| * | |
| * @param _spender The address authorized to spend | |
| * @param _value the max amount they can spend | |
| * @param _extraData some extra information to send to the approved contract | |
| */ | |
| function approveAndCall(address _spender, uint256 _value, bytes _extraData) | |
| public | |
| returns (bool success) { | |
| tokenRecipient spender = tokenRecipient(_spender); | |
| if (approve(_spender, _value)) { | |
| spender.receiveApproval(msg.sender, _value, this, _extraData); | |
| return true; | |
| } | |
| } | |
| /** | |
| * Destroy tokens | |
| * | |
| * Remove `_value` tokens from the system irreversibly | |
| * | |
| * @param _value the amount of money to burn | |
| */ | |
| function burn(uint256 _value) public returns (bool success) { | |
| require(balanceOf[msg.sender] >= _value); // Check if the sender has enough | |
| balanceOf[msg.sender] -= _value; // Subtract from the sender | |
| totalSupply -= _value; // Updates totalSupply | |
| emit Burn(msg.sender, _value); | |
| return true; | |
| } | |
| /** | |
| * Destroy tokens from other account | |
| * | |
| * Remove `_value` tokens from the system irreversibly on behalf of `_from`. | |
| * | |
| * @param _from the address of the sender | |
| * @param _value the amount of money to burn | |
| */ | |
| function burnFrom(address _from, uint256 _value) public returns (bool success) { | |
| require(balanceOf[_from] >= _value); // Check if the targeted balance is enough | |
| require(_value <= allowance[_from][msg.sender]); // Check allowance | |
| balanceOf[_from] -= _value; // Subtract from the targeted balance | |
| allowance[_from][msg.sender] -= _value; // Subtract from the sender's allowance | |
| totalSupply -= _value; // Update totalSupply | |
| emit Burn(_from, _value); | |
| return true; | |
| } | |
| } |
https://github.com/OpenZeppelin/zeppelin-solidity
npm install -E zeppelin-solidity
import 'zeppelin-solidity/contracts/ownership/Ownable.sol';
contract MyContract is Ownable {
...
}
https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/math/SafeMath.sol
https://github.com/ethereum/wiki/wiki/Safety#recommendations-for-smart-contract-security-in-solidity
https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/payment/PullPayment.sol
'''
import './PullPayment.sol';
contract GoodArrayUse is PullPayment {
address[] employees;
mapping(address => uint) bonuses;
function payBonus() {
for (uint i = 0; i < employees.length; i++) {
address employee = employees[i];
uint bonus = bonuses[employee];
asyncSend(employee, bonus);
}
}
function calculateBonus(address employee) returns (uint) {
uint bonus = 0;
// some expensive computation...
bonuses[employee] = bonus;
}
}
'''
https://www.ethereum.org/crowdsale
https://www.ethereum.org/dao
https://www.ethereum.org/token
https://ethereum.org/dao
http://truffleframework.com/tutorials/robust-smart-contracts-with-openzeppelin
http://truffleframework.com/tutorials/pet-shop
http://truffleframework.com/ganache/
https://blog.zeppelin.solutions/onward-with-ethereum-smart-contract-security-97a827e47702