diff --git a/dapp-30/day1-simple-smart-contract/smart-contract-solidity-0-8-update/SimpleSmartContract.sol b/dapp-30/day1-simple-smart-contract/smart-contract-solidity-0-8-update/SimpleSmartContract.sol new file mode 100644 index 0000000000..a0699fd9c9 --- /dev/null +++ b/dapp-30/day1-simple-smart-contract/smart-contract-solidity-0-8-update/SimpleSmartContract.sol @@ -0,0 +1,4 @@ +pragma solidity ^0.8.0; + +contract SimpleSmartContract { +} diff --git a/dapp-30/day10-escrow/smart-contract-solidity-0-8-update/Escrow.sol b/dapp-30/day10-escrow/smart-contract-solidity-0-8-update/Escrow.sol new file mode 100644 index 0000000000..6dcd34da02 --- /dev/null +++ b/dapp-30/day10-escrow/smart-contract-solidity-0-8-update/Escrow.sol @@ -0,0 +1,33 @@ +pragma solidity ^0.8.0; + +contract Escrow{ + address public payer; + address payable public payee; + address public lawyer; + uint public amount; + + constructor( + address _payer, + address payable _payee, + uint _amount) { + payer = _payer; + payee = _payee; + lawyer = msg.sender; + amount = _amount; + } + + function deposit() payable public { + require(msg.sender == payer, 'Sender must be the payer'); + require(address(this).balance <= amount, 'Cant send more than escrow amount'); + } + + function release() public { + require(address(this).balance == amount, 'cannot release funds before full amount is sent'); + require(msg.sender == lawyer, 'only lawyer can release funds'); + payee.transfer(amount); + } + + function balanceOf() view public returns(uint) { + return address(this).balance; + } +} diff --git a/dapp-30/day10-escrow/smart-contract/Escrow.sol b/dapp-30/day10-escrow/smart-contract/Escrow.sol index ef6df6319f..21a8792925 100644 --- a/dapp-30/day10-escrow/smart-contract/Escrow.sol +++ b/dapp-30/day10-escrow/smart-contract/Escrow.sol @@ -18,7 +18,7 @@ contract Escrow{ } function deposit() payable public { - require(msg.sender = payer, 'Sender must be the payer'); + require(msg.sender == payer, 'Sender must be the payer'); require(address(this).balance <= amount, 'Cant send more than escrow amount'); } diff --git a/dapp-30/day11-string-manipulation/smart-contract-solidity-0-8-update/Strings.sol b/dapp-30/day11-string-manipulation/smart-contract-solidity-0-8-update/Strings.sol new file mode 100644 index 0000000000..882c638473 --- /dev/null +++ b/dapp-30/day11-string-manipulation/smart-contract-solidity-0-8-update/Strings.sol @@ -0,0 +1,27 @@ +pragma solidity ^0.8.0; + +contract Strings { + function length(string memory str) pure public returns(uint) { + bytes memory str_bytes = bytes(str); + return str_bytes.length; + } + + function concatenate(string memory str1, string memory str2) pure public returns(string memory) { + bytes memory str_bytes1 = bytes(str1); + bytes memory str_bytes2 = bytes(str2); + string memory str = new string(str_bytes1.length + str_bytes2.length); + bytes memory str_bytes = bytes(str); + + uint k = 0; + for(uint i = 0; i < str_bytes1.length; i++) { + str_bytes[k] = str_bytes1[i]; + k++; + } + for(uint i = 0; i < str_bytes2.length; i++) { + str_bytes[k] = str_bytes2[i]; + k++; + } + + return string(str_bytes); + } +} diff --git a/dapp-30/day12-fibonacci/smart-contract-solidity-0-8-update/Fibonacci.sol b/dapp-30/day12-fibonacci/smart-contract-solidity-0-8-update/Fibonacci.sol new file mode 100644 index 0000000000..58e513e569 --- /dev/null +++ b/dapp-30/day12-fibonacci/smart-contract-solidity-0-8-update/Fibonacci.sol @@ -0,0 +1,17 @@ +pragma solidity ^0.8.0; + +contract Fibonacci { + function fib(uint n) pure external returns(uint) { + if(n == 0) { + return 0; + } + uint fi_1 = 1; + uint fi_2 = 1; + for(uint i = 2; i < n; i++) { + uint fi = fi_1 + fi_2; + fi_2 = fi_1; + fi_1 = fi; + } + return fi_1; + } +} diff --git a/dapp-30/day13-multisig-wallet/smart-contract-solidity-0-8-update/Multisig.sol b/dapp-30/day13-multisig-wallet/smart-contract-solidity-0-8-update/Multisig.sol new file mode 100644 index 0000000000..a34a263499 --- /dev/null +++ b/dapp-30/day13-multisig-wallet/smart-contract-solidity-0-8-update/Multisig.sol @@ -0,0 +1,59 @@ +pragma solidity ^0.8.0; + +contract Wallet { + address[] public approvers; + uint public quorum; + struct Transfer { + uint id; + uint amount; + address payable to; + uint approvals; + bool sent; + } + mapping(uint => Transfer) transfers; + uint nextId; + mapping(address => mapping(uint => bool)) approvals; + + constructor(address[] memory _approvers, uint _quorum) payable { + approvers = _approvers; + quorum = _quorum; + } + + function createTransfer(uint amount, address payable to) onlyApprover() external { + transfers[nextId] = Transfer( + nextId, + amount, + to, + 0, + false + ); + nextId++; + } + + function sendTransfer(uint id) onlyApprover() external { + require(transfers[id].sent == false, 'transfer has already been sent'); + if(transfers[id].approvals >= quorum) { + transfers[id].sent = true; + address payable to = transfers[id].to; + uint amount = transfers[id].amount; + to.transfer(amount); + return; + } + //BUG: put this BEFORE if(transfers[id].approvals >= quorum) + if(approvals[msg.sender][id] == false) { + approvals[msg.sender][id] = true; + transfers[id].approvals++; + } + } + + modifier onlyApprover() { + bool allowed = false; + for(uint i; i < approvers.length; i++) { + if(approvers[i] == msg.sender) { + allowed = true; + } + } + require(allowed == true, 'only approver allowed'); + _; + } +} diff --git a/dapp-30/day14-voting/smart-contract-solidity-0-8-update/Voting.sol b/dapp-30/day14-voting/smart-contract-solidity-0-8-update/Voting.sol new file mode 100644 index 0000000000..5ad2525d3a --- /dev/null +++ b/dapp-30/day14-voting/smart-contract-solidity-0-8-update/Voting.sol @@ -0,0 +1,68 @@ +pragma solidity ^0.8.0; + +contract Voting { + mapping(address => bool) public voters; + struct Choice { + uint id; + string name; + uint votes; + } + struct Ballot { + uint id; + string name; + Choice[] choices; + uint end; + } + mapping(uint => Ballot) ballots; + uint nextBallotId; + address public admin; + mapping(address => mapping(uint => bool)) votes; + + constructor() { + admin = msg.sender; + } + + function addVoters(address[] calldata _voters) external onlyAdmin() { + for(uint i = 0; i < _voters.length; i++) { + voters[_voters[i]] = true; + } + } + + function createBallot( + string memory name, + string[] memory _choices, + uint offset + ) public onlyAdmin() { + ballots[nextBallotId].id = nextBallotId; + ballots[nextBallotId].name = name; + ballots[nextBallotId].end = now + offset; + for(uint i = 0; i < _choices.length ; i++) { + ballots[nextBallotId].choices.push(Choice(i, _choices[i], 0)); + } + nextBallotId++; + } + + function vote(uint ballotId, uint choiceId) external { + require(voters[msg.sender] == true, 'only voters can vote'); + require(votes[msg.sender][ballotId] == false, 'voter can only vote once for a ballot'); + require(now < ballots[ballotId].end, 'can only vote until ballot end date'); + votes[msg.sender][ballotId] = true; + ballots[ballotId].choices[choiceId].votes++; + } + + //If `pragma experimental ABIEncoderV2` + function results(uint ballotId) + view + external + returns(Choice[] memory) { + require(now >= ballots[ballotId].end, 'cannot see the ballot result before ballot end'); + return ballots[ballotId].choices; + } + + modifier onlyAdmin() { + require(msg.sender == admin, 'only admin'); + _; + } +} + + diff --git a/dapp-30/day15-dao/smart-contract-solidity-0-8-update/DAO.sol b/dapp-30/day15-dao/smart-contract-solidity-0-8-update/DAO.sol new file mode 100644 index 0000000000..95d1c90266 --- /dev/null +++ b/dapp-30/day15-dao/smart-contract-solidity-0-8-update/DAO.sol @@ -0,0 +1,129 @@ +pragma solidity ^0.8.0; + +/** + * DAO contract: + * 1. Collects investors money (ether) & allocate shares + * 2. Keep track of investor contributions with shares + * 3. Allow investors to transfer shares + * 4. allow investment proposals to be created and voted + * 5. execute successful investment proposals (i.e send money) + */ + +contract DAO { + struct Proposal { + uint id; + string name; + uint amount; + address payable recipient; + uint votes; + uint end; + bool executed; + } + + mapping(address => bool) public investors; + mapping(address => uint) public shares; + mapping(address => mapping(uint => bool)) public votes; + mapping(uint => Proposal) public proposals; + uint public totalShares; + uint public availableFunds; + uint public contributionEnd; + uint public nextProposalId; + uint public voteTime; + uint public quorum; + address public admin; + + constructor( + uint contributionTime, + uint _voteTime, + uint _quorum) { + require(_quorum > 0 && _quorum < 100, 'quorum must be between 0 and 100'); + contributionEnd = block.timestamp + contributionTime; + voteTime = _voteTime; + quorum = _quorum; + admin = msg.sender; + } + + function contribute() payable external { + require(block.timestamp < contributionEnd, 'cannot contribute after contributionEnd'); + investors[msg.sender] = true; + shares[msg.sender] += msg.value; + totalShares += msg.value; + availableFunds += msg.value; + } + + function redeemShare(uint amount) external { + require(shares[msg.sender] >= amount, 'not enough shares'); + require(availableFunds >= amount, 'not enough available funds'); + shares[msg.sender] -= amount; + availableFunds -= amount; + payable(msg.sender).transfer(amount); + } + + function transferShare(uint amount, address to) external { + require(shares[msg.sender] >= amount, 'not enough shares'); + shares[msg.sender] -= amount; + shares[to] += amount; + investors[to] = true; + } + + function createProposal( + string memory name, + uint amount, + address payable recipient) + public + onlyInvestors() { + require(availableFunds >= amount, 'amount too big'); + proposals[nextProposalId] = Proposal( + nextProposalId, + name, + amount, + recipient, + 0, + block.timestamp + voteTime, + false + ); + availableFunds -= amount; + nextProposalId++; + } + + function vote(uint proposalId) external onlyInvestors() { + Proposal storage proposal = proposals[proposalId]; + require(votes[msg.sender][proposalId] == false, 'investor can only vote once for a proposal'); + require(block.timestamp < proposal.end, 'can only vote until proposal end date'); + votes[msg.sender][proposalId] = true; + proposal.votes += shares[msg.sender]; + } + + function executeProposal(uint proposalId) external onlyAdmin() { + Proposal storage proposal = proposals[proposalId]; + require(block.timestamp >= proposal.end, 'cannot execute proposal before end date'); + require(proposal.executed == false, 'cannot execute proposal already executed'); + require((proposal.votes / totalShares) * 100 >= quorum, 'cannot execute proposal with votes # below quorum'); + _transferEther(proposal.amount, proposal.recipient); + } + + function withdrawEther(uint amount, address payable to) external onlyAdmin() { + _transferEther(amount, to); + } + + function _transferEther(uint amount, address payable to) internal { + require(amount <= availableFunds, 'not enough availableFunds'); + availableFunds -= amount; + to.transfer(amount); + } + + //For ether returns of proposal investments + receive() external payable { + availableFunds += msg.value; + } + + modifier onlyInvestors() { + require(investors[msg.sender] == true, 'only investors'); + _; + } + + modifier onlyAdmin() { + require(msg.sender == admin, 'only admin'); + _; + } +} diff --git a/dapp-30/day16-loan-state-machine/smart-contract-solidity-0-8-update/StateMachine.sol b/dapp-30/day16-loan-state-machine/smart-contract-solidity-0-8-update/StateMachine.sol new file mode 100644 index 0000000000..4883db93d9 --- /dev/null +++ b/dapp-30/day16-loan-state-machine/smart-contract-solidity-0-8-update/StateMachine.sol @@ -0,0 +1,59 @@ +pragma solidity ^0.8.0; + +contract StateMachine { + enum State { + PENDING, + ACTIVE, + CLOSED + } + State public state = State.PENDING; + uint public amount; + uint public interest; + uint public end; + uint public duration; + address payable public borrower; + address payable public lender; + + constructor( + uint _amount, + uint _interest, + uint _duration, + address payable _borrower, + address payable _lender + ) { + amount = _amount; + interest = _interest; + duration = _duration; + borrower = _borrower; + lender = _lender; + } + + function fund() payable external { + require(msg.sender == lender, 'only lender can lend'); + require(address(this).balance == amount, 'can only lend the exact amount'); + _transitionTo(State.ACTIVE); + borrower.transfer(amount); + } + + function reimburse() payable external { + require(msg.sender == borrower, 'only borrower can reimburse'); + require(msg.value == amount + interest, 'borrower need to reimburse exactly amount + interest'); + _transitionTo(State.CLOSED); + lender.transfer(amount + interest); + } + + function _transitionTo(State to) internal { + require(to != State.PENDING, 'cannot go back to pending'); + require(to != state, 'cannot transition to same state'); + if(to == State.ACTIVE) { + require(state == State.PENDING, 'cannot only go to active from pending'); + state = State.ACTIVE; + end = block.timestamp + duration; + } + if(to == State.CLOSED) { + require(state == State.ACTIVE, 'cannot only go to closed from active'); + require(block.timestamp >= end, 'loan hasnt matured yet'); + state = State.CLOSED; + } + } +} diff --git a/dapp-30/day17-event-organization/smart-contract-solidity-0-8-update/Event.sol b/dapp-30/day17-event-organization/smart-contract-solidity-0-8-update/Event.sol new file mode 100644 index 0000000000..9529fcc08f --- /dev/null +++ b/dapp-30/day17-event-organization/smart-contract-solidity-0-8-update/Event.sol @@ -0,0 +1,64 @@ +pragma solidity ^0.8.0; + +contract EventContract { + struct Event { + address admin; + string name; + uint date; + uint price; + uint ticketCount; + uint ticketRemaining; + } + mapping(uint => Event) public events; + mapping(address => mapping(uint => uint)) public tickets; + uint public nextId; + + function createEvent( + string calldata name, + uint date, + uint price, + uint ticketCount) + external { + require(date > block.timestamp, 'can only organize event at a future date'); + require(ticketCount > 0, 'can only organize event with at least 1 ticket'); + events[nextId] = Event( + msg.sender, + name, + date, + price, + ticketCount, + ticketCount + ); + nextId++; + } + + function buyTicket(uint id, uint quantity) + eventExist(id) + eventActive(id) + payable + external { + Event storage _event = events[id]; + require(msg.value == (_event.price * quantity), 'ether sent must be equal to total ticket cost'); + require(_event.ticketRemaining >= quantity, 'not enough ticket left'); + _event.ticketRemaining -= quantity; + tickets[msg.sender][id] += quantity; + } + + function transferTicket(uint eventId, uint quantity, address to) + eventExist(eventId) + eventActive(eventId) + external { + require(tickets[msg.sender][eventId] >= quantity, 'not enough ticket'); + tickets[msg.sender][eventId] -= quantity; + tickets[to][eventId] += quantity; + } + + modifier eventExist(uint id) { + require(events[id].date != 0, 'this event does not exist'); + _; + } + modifier eventActive(uint id) { + require(block.timestamp < events[id].date, 'event must be active'); + _; + } +} diff --git a/dapp-30/day18-lottery/smart-contract-solidity-0-8-update/Lottery.sol b/dapp-30/day18-lottery/smart-contract-solidity-0-8-update/Lottery.sol new file mode 100644 index 0000000000..3bbe7e2a10 --- /dev/null +++ b/dapp-30/day18-lottery/smart-contract-solidity-0-8-update/Lottery.sol @@ -0,0 +1,68 @@ +pragma solidity ^0.8.0; + +contract Lottery { + enum State { + IDLE, + BETTING + } + address payable[] public players; + State public currentState = State.IDLE; + uint public betCount; + uint public betSize; + uint public houseFee; + address public admin; + + constructor(uint fee) public { + require(fee > 1 && fee < 99, 'fee should be between 1 and 99'); + admin = msg.sender; + houseFee = fee; + } + + function createBet(uint count, uint size) + external + inState(State.IDLE) + onlyAdmin() { + betCount = count; + betSize = size; + currentState = State.BETTING; + } + + function bet() + external + payable + inState(State.BETTING) { + require(msg.value == betSize, 'can only bet exactly the bet size'); + players.push(payable(msg.sender)); + if(players.length == betCount ) { + uint winner = _randomModulo(betCount); + players[winner].transfer((betSize * betCount) * (100 - houseFee) / 100); + currentState = State.IDLE; + delete players; + } + } + + function cancel() + external + inState(State.BETTING) + onlyAdmin() { + for(uint i = 0; i < players.length; i++) { + players[i].transfer(betSize); + } + delete players; + currentState = State.IDLE; + } + + function _randomModulo(uint modulo) view internal returns(uint) { + return uint(keccak256(abi.encodePacked(block.timestamp, block.difficulty))) % modulo; + } + + modifier inState(State state) { + require(state == currentState, 'current state does not allow this'); + _; + } + + modifier onlyAdmin() { + require(msg.sender == admin, 'only admin'); + _; + } +} diff --git a/dapp-30/day19-fomo3d/smart-contract-solidity-0-8-update/Fomo3D.sol b/dapp-30/day19-fomo3d/smart-contract-solidity-0-8-update/Fomo3D.sol new file mode 100644 index 0000000000..9b0dc25de0 --- /dev/null +++ b/dapp-30/day19-fomo3d/smart-contract-solidity-0-8-update/Fomo3D.sol @@ -0,0 +1,90 @@ +pragma solidity ^0.8.0; + +contract Fomo3D { + enum State { + INACTIVE, + ACTIVE + } + State currentState = State.INACTIVE; + address payable public king; + uint public start; + uint public end; + uint public hardEnd; + uint public pot; + uint public houseFee = 2; + uint public initialKeyPrice; + uint public totalKeys; + address payable[] public keyHolders; + mapping(address => uint) keys; + + function kickStart() + external + inState(State.INACTIVE) { + currentState = State.ACTIVE; + _createRound(); + } + + function bet() + external + payable + inState(State.ACTIVE) { + if(block.timestamp > end || block.timestamp > hardEnd) { + payable(msg.sender).transfer(msg.value); + _distribute(); + _createRound(); + return; + } + + //Keys + uint keyCount = msg.value / getKeyPrice(); + keys[msg.sender] += keyCount; + totalKeys += keyCount; + bool alreadyAdded = false; + for(uint i = 0; i < keyHolders.length; i++) { + if(keyHolders[i] == msg.sender) { + alreadyAdded = true; + } + } + if(alreadyAdded == false) { + keyHolders.push(payable(msg.sender)); + } + + //Other + pot += msg.value; + end = end + 30 > hardEnd ? hardEnd : end + 30; + } + + function getKeyPrice() view public returns(uint) { + uint periodCount = (block.timestamp - start) / 30; + return initialKeyPrice + periodCount * 0.01 ether; + } + + function _distribute() internal { + uint netPot = pot * (100 - houseFee) / 100; + king.transfer((netPot * 50) / 100); + for(uint i = 0; i < keyHolders.length; i++) { + address payable keyHolder = keyHolders[i]; + if(keyHolder != king) { + (keyHolder).transfer(((netPot * 50) / 100) * (keys[keyHolder] / totalKeys)); + } + } + } + + function _createRound() internal { + for(uint i = 0; i < keyHolders.length; i++) { + delete keys[keyHolders[i]]; + } + delete keyHolders; + totalKeys = 0; + start = block.timestamp; + end = block.timestamp + 30; + hardEnd = block.timestamp + 86400; + initialKeyPrice = 1 ether; + } + + modifier inState(State state) { + require(currentState == state, 'not possible in current state'); + _; + } + +} diff --git a/dapp-30/day2-hello-world/smart-contract-solidity-0-8-update/HelloWorld.sol b/dapp-30/day2-hello-world/smart-contract-solidity-0-8-update/HelloWorld.sol new file mode 100644 index 0000000000..156ca52b00 --- /dev/null +++ b/dapp-30/day2-hello-world/smart-contract-solidity-0-8-update/HelloWorld.sol @@ -0,0 +1,7 @@ +pragma solidity ^0.8.0; + +contract HelloWorld { + function hello() pure public returns(string memory) { + return 'Hello World'; + } +} diff --git a/dapp-30/day20-rock-paper-scissors/smart-contract-solidity-0-8-update/RockPaperScissors.sol b/dapp-30/day20-rock-paper-scissors/smart-contract-solidity-0-8-update/RockPaperScissors.sol new file mode 100644 index 0000000000..87d23f42a3 --- /dev/null +++ b/dapp-30/day20-rock-paper-scissors/smart-contract-solidity-0-8-update/RockPaperScissors.sol @@ -0,0 +1,93 @@ +pragma solidity ^0.8.0; + +contract RockPaperScissors { + enum State { + CREATED, + JOINED, + COMMITED, + REVEALED + } + struct Game { + uint id; + uint bet; + address payable[] players; + State state; + } + struct Move { + bytes32 hash; + uint value; + } + mapping(uint => Game) public games; + mapping(uint => mapping(address => Move)) public moves; + mapping(uint => uint) public winningMoves; + uint public gameId; + + constructor() { + winningMoves[1] = 3; + winningMoves[2] = 1; + winningMoves[3] = 2; + } + + function createGame(address payable participant) external payable { + require(msg.value > 0, 'have to send some ether'); + address payable[] memory players = new address payable[](2); + players[0] = payable(msg.sender); + players[1] = participant; + + games[gameId] = Game( + gameId, + msg.value, + players, + State.CREATED + ); + gameId++; + } + + function joinGame(uint _gameId) external payable { + Game storage game = games[_gameId]; + require(msg.sender == game.players[1], 'sender must be second player'); //also throw if game does not exist + require(msg.value >= game.bet, 'not enough ether sent'); + require(game.state == State.CREATED, 'game must be in CREATED state'); + if(msg.value > game.bet) { + payable(msg.sender).transfer(msg.value - game.bet); + } + game.state = State.JOINED; + } + + function commitMove(uint _gameId, uint moveId, uint salt) external { + Game storage game = games[_gameId]; + require(game.state == State.JOINED, 'game must be in JOINED state'); + require(msg.sender == game.players[0] || msg.sender == game.players[1], 'can only be called by one of players'); + require(moves[_gameId][msg.sender].hash == 0, 'move already made'); // if no move yet, it will default to 0 + require(moveId == 1 || moveId == 2 || moveId == 3, 'move needs to be 1, 2 or 3'); + moves[_gameId][msg.sender] = Move(keccak256(abi.encodePacked(moveId, salt)), 0); + if(moves[_gameId][game.players[0]].hash != 0 + && moves[_gameId][game.players[1]].hash != 0) { + game.state = State.COMMITED; + } + } + + function revealMove(uint _gameId, uint moveId, uint salt) external { + Game storage game = games[_gameId]; + Move storage move1 = moves[_gameId][game.players[0]]; + Move storage move2 = moves[_gameId][game.players[1]]; + Move storage moveSender = moves[_gameId][msg.sender]; + require(game.state == State.COMMITED, 'game must be in COMMITED state'); + require(msg.sender == game.players[0] || msg.sender == game.players[1], 'can only be called by one of players'); + require(moveSender.hash == keccak256(abi.encodePacked(moveId, salt)), 'moveId does not match commitment'); + moveSender.value = moveId; + if(move1.value != 0 + && move2.value != 0) { + if(move1.value == move2.value) { + game.players[0].transfer(game.bet); + game.players[1].transfer(game.bet); + game.state = State.REVEALED; + return; + } + address payable winner; + winner = winningMoves[move1.value] == move2.value ? game.players[0] : game.players[1]; + winner.transfer(2* game.bet); + game.state = State.REVEALED; + } + } +} diff --git a/dapp-30/day3-simple-storage/smart-contract-solidity-0-8-update/SimpleStorage.sol b/dapp-30/day3-simple-storage/smart-contract-solidity-0-8-update/SimpleStorage.sol new file mode 100644 index 0000000000..26424a2c4b --- /dev/null +++ b/dapp-30/day3-simple-storage/smart-contract-solidity-0-8-update/SimpleStorage.sol @@ -0,0 +1,13 @@ +pragma solidity ^0.8.0; + +contract SimpleStorage { + string public data; + + function set(string memory _data) public { + data = _data; + } + + function get() view public returns(string memory) { + return data; + } +} diff --git a/dapp-30/day4-advanced-storage/smart-contract-solidity-0-8-update/AdvancedStorage.sol b/dapp-30/day4-advanced-storage/smart-contract-solidity-0-8-update/AdvancedStorage.sol new file mode 100644 index 0000000000..2012702ea7 --- /dev/null +++ b/dapp-30/day4-advanced-storage/smart-contract-solidity-0-8-update/AdvancedStorage.sol @@ -0,0 +1,21 @@ +pragma solidity ^0.8.0; + +contract AdvancedStorage { + uint[] public ids; + + function add(uint id) public { + ids.push(id); + } + + function get(uint i) view public returns(uint) { + return ids[i]; + } + + function getAll() view public returns(uint[] memory) { + return ids; + } + + function length() view public returns(uint) { + return ids.length; + } +} diff --git a/dapp-30/day5-crud/smart-contract-solidity-0-8-update/Crud.sol b/dapp-30/day5-crud/smart-contract-solidity-0-8-update/Crud.sol new file mode 100644 index 0000000000..e6530b25e9 --- /dev/null +++ b/dapp-30/day5-crud/smart-contract-solidity-0-8-update/Crud.sol @@ -0,0 +1,40 @@ +pragma solidity ^0.8.0; + +contract Crud { + struct User { + uint id; + string name; + } + User[] public users; + uint public nextId = 1; + + function create(string memory name) public { + users.push(User(nextId, name)); + nextId++; + } + + function read(uint id) view public returns(uint, string memory) { + uint i = find(id); + return(users[i].id, users[i].name); + } + + function update(uint id, string memory name) public { + uint i = find(id); + users[i].name = name; + } + + function destroy(uint id) public { + uint i = find(id); + delete users[i]; + } + + function find(uint id) view internal returns(uint) { + for(uint i = 0; i < users.length; i++) { + if(users[i].id == id) { + return i; + } + } + revert('User does not exist!'); + } + +} diff --git a/dapp-30/day6-ether-wallet/smart-contract-solidity-0-8-update/EtherWallet.sol b/dapp-30/day6-ether-wallet/smart-contract-solidity-0-8-update/EtherWallet.sol new file mode 100644 index 0000000000..4ad3d4374c --- /dev/null +++ b/dapp-30/day6-ether-wallet/smart-contract-solidity-0-8-update/EtherWallet.sol @@ -0,0 +1,24 @@ +pragma solidity ^0.8.0; + +contract EtherWallet { + address payable public owner; + + constructor(address payable _owner) { + owner = _owner; + } + + function deposit() payable public { + } + + function send(address payable to, uint amount) public { + if(msg.sender == owner) { + to.transfer(amount); + return; + } + revert('sender is not allowed'); + } + + function balanceOf() view public returns(uint) { + return address(this).balance; + } +} diff --git a/dapp-30/day7-split-payment/smart-contract-solidity-0-8-update/SplitPayment.sol b/dapp-30/day7-split-payment/smart-contract-solidity-0-8-update/SplitPayment.sol new file mode 100644 index 0000000000..2a9e18de4c --- /dev/null +++ b/dapp-30/day7-split-payment/smart-contract-solidity-0-8-update/SplitPayment.sol @@ -0,0 +1,24 @@ +pragma solidity ^0.8.0; + +contract SplitPayment { + address owner; + + constructor(address _owner) { + owner = _owner; + } + + function send(address payable[] memory to, uint[] memory amount ) + payable + public + ownerOnly { + require(to.length == amount.length, 'to must be same length as amount'); + for(uint i = 0; i < to.length; i++) { + to[i].transfer(amount[i]); + } + } + + modifier ownerOnly() { + require(msg.sender == owner); + _; + } +} diff --git a/dapp-30/day8-deed/smart-contract-solidity-0-8-update/Deed.sol b/dapp-30/day8-deed/smart-contract-solidity-0-8-update/Deed.sol new file mode 100644 index 0000000000..c75d0e616e --- /dev/null +++ b/dapp-30/day8-deed/smart-contract-solidity-0-8-update/Deed.sol @@ -0,0 +1,23 @@ +pragma solidity ^0.8.0; + +contract Deed { + address public lawyer; + address payable public beneficiary; + uint public earliest; + + constructor( + address _lawyer, + address payable _beneficiary, + uint fromNow) + payable { + lawyer = _lawyer; + beneficiary = _beneficiary; + earliest = block.timestamp + fromNow; + } + + function withdraw() public { + require(msg.sender == lawyer, 'lawyer only'); + require(block.timestamp >= earliest, 'too early'); + beneficiary.transfer(address(this).balance); + } +} diff --git a/dapp-30/day9-deed-multi-payouts/smart-contract-solidity-0-8-update/DeedMultiPayout.sol b/dapp-30/day9-deed-multi-payouts/smart-contract-solidity-0-8-update/DeedMultiPayout.sol new file mode 100644 index 0000000000..e3036e0307 --- /dev/null +++ b/dapp-30/day9-deed-multi-payouts/smart-contract-solidity-0-8-update/DeedMultiPayout.sol @@ -0,0 +1,34 @@ +pragma solidity ^0.8.0; + +contract DeedMultiPayout { + address public lawyer; + address payable public beneficiary; + uint public earliest; + uint public amount; + uint constant public PAYOUTS = 10; + uint constant public INTERVAL = 10; + uint public paidPayouts; + + constructor( + address _lawyer, + address payable _beneficiary, + uint fromNow) + payable { + lawyer = _lawyer; + beneficiary = _beneficiary; + earliest = block.timestamp + fromNow; + amount = msg.value / PAYOUTS; + } + + function withdraw() public { + require(msg.sender == beneficiary, 'beneficiary only'); + require(block.timestamp >= earliest, 'too early'); + require(paidPayouts < PAYOUTS, 'no payout left'); + + uint elligiblePayouts = (block.timestamp - earliest) / INTERVAL; + uint duePayouts = elligiblePayouts - paidPayouts; + duePayouts = duePayouts + paidPayouts > PAYOUTS ? PAYOUTS - paidPayouts : duePayouts; + paidPayouts += duePayouts; + beneficiary.transfer(duePayouts * amount); + } +}