Skip to content

Commit

Permalink
finished Lesson 7
Browse files Browse the repository at this point in the history
  • Loading branch information
FifthRooter committed Dec 10, 2021
1 parent e8ebab6 commit 6587612
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 15 deletions.
2 changes: 2 additions & 0 deletions smart-contract-lottery/brownie-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ compiler:
remappings:
- "@chainlink=smartcontractkit/[email protected]"
- "@openzeppelin=OpenZeppelin/[email protected]"
dotenv: .env
networks:
default: development
development:
Expand All @@ -17,6 +18,7 @@ networks:
link_token: "0x01BE23585060835E02B77ef475b0Cc51aA1e0709"
keyhash: "0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311"
fee: 1_000_000_000_000_000_00
verify: true
mainnet-fork:
eth_usd_price_feed: "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419"
wallets:
Expand Down
6 changes: 4 additions & 2 deletions smart-contract-lottery/contracts/Lottery.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ contract Lottery is VRFConsumerBase, Ownable {
LOTTERY_STATE public lottery_state;
uint256 public fee;
bytes32 public keyHash;
event RequestedRandomness(bytes32 requestId);


constructor(
Expand All @@ -33,7 +34,7 @@ contract Lottery is VRFConsumerBase, Ownable {
uint256 _fee,
bytes32 _keyHash
) public VRFConsumerBase(_vrfCoordinator, _link){
usdEntryFee = 50 * (10**28);
usdEntryFee = 50 * (10**18);
ethUsdPriceFeed = AggregatorV3Interface(_priceFeedAddress);
lottery_state = LOTTERY_STATE.CLOSED;
fee = _fee;
Expand Down Expand Up @@ -72,14 +73,15 @@ contract Lottery is VRFConsumerBase, Ownable {
// Chainlink VRF offers Verifiable Randomness (provable random number)
lottery_state = LOTTERY_STATE.CALCULATING_WINNER;
bytes32 requestId = requestRandomness(keyHash, fee);
emit RequestedRandomness(requestId);
}

function fulfillRandomness(bytes32 _requestId, uint256 _randomness) internal override{
require(lottery_state == LOTTERY_STATE.CALCULATING_WINNER, "You aren't there yet!");
require(_randomness > 0, "random-not-found");
uint256 indexOfWinner = _randomness % players.length;
recentWinner = players[indexOfWinner];
recentWinner.transfer(address(this). balance);
recentWinner.transfer(address(this).balance);
// Reset the lottery
players = new address payable[](0);
LOTTERY_STATE.CLOSED;
Expand Down
16 changes: 16 additions & 0 deletions smart-contract-lottery/interfaces/LinkTokenInterface.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
pragma solidity ^0.6.6;

interface LinkTokenInterface {
function allowance(address owner, address spender) external view returns (uint256 remaining);
function approve(address spender, uint256 value) external returns (bool success);
function balanceOf(address owner) external view returns (uint256 balance);
function decimals() external view returns (uint8 decimalPlaces);
function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
function increaseApproval(address spender, uint256 subtractedValue) external;
function name() external view returns (string memory tokenName);
function symbol() external view returns (string memory tokenSymbol);
function totalSupply() external view returns (uint256 totalTokensIssued);
function transfer(address to, uint256 value) external returns (bool success);
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success);
function transferFrom(address from, address to, uint256 value) external returns (bool success);
}
38 changes: 36 additions & 2 deletions smart-contract-lottery/scripts/deploy_lottery.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from scripts.helpers import get_account, get_contract, config
from scripts.helpers import get_account, get_contract, config, fund_with_link
from brownie import Lottery, network, config
import time

def deploy_lottery():
account = get_account()
Expand All @@ -13,6 +14,39 @@ def deploy_lottery():
publish_source=config['networks'][network.show_active()].get('verify', False)
)
print('Deployed Lottery!')
return lottery

def start_lottery():
account = get_account()
lottery = Lottery[-1]
starting_tx = lottery.startLottery({'from':account})
starting_tx.wait(1)
print('The lottery has started!')

def enter_lottery():
account = get_account()
lottery = Lottery[-1]
value = lottery.getEntranceFee()
print(f'Entrance fee is: {value}')
tx = lottery.enter({'from': account, 'value': value})
tx.wait(1)
print('You entered the lottery!')

def end_lottery():
account = get_account()
lottery = Lottery[-1]
# 1) Fund the contract
# 2) End the lottery
tx = fund_with_link(lottery.address)
tx.wait(1)

ending_transaction = lottery.endLottery({'from': account})
ending_transaction.wait(1)
time.sleep(120)
print(f'{lottery.recentWinner()} is the new winner!')

def main():
deploy_lottery()
deploy_lottery()
start_lottery()
enter_lottery()
end_lottery()
11 changes: 10 additions & 1 deletion smart-contract-lottery/scripts/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
Contract,
MockV3Aggregator,
VRFCoordinatorMock,
LinkToken
LinkToken,
interface
)

FORKED_LOCAL_ENVIRONMENTS = ['mainnet-fork', 'mainnet-fork-dev']
Expand Down Expand Up @@ -67,3 +68,11 @@ def deploy_mocks(decimals=DECIMALS, initial_value=INITIAL_VALUE):
VRFCoordinatorMock.deploy(link_token.address, {'from': account})
print('deployed')

def fund_with_link(contract_address, account=None, link_token=None, amount=1_000_000_000_000_000_00):
account = account if account else get_account()
link_token = link_token if link_token else get_contract('link_token')
tx = link_token.transfer(contract_address, amount, {'from': account})
tx.wait(1)
print('Fund contract')
return tx

Empty file.
10 changes: 0 additions & 10 deletions smart-contract-lottery/tests/test_lottery.py

This file was deleted.

19 changes: 19 additions & 0 deletions smart-contract-lottery/tests/test_lottery_integration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from brownie import network
import pytest
from scripts.helpers import LOCAL_BLOCKCHAIN_ENVIRONMENTS, get_account, get_contract, fund_with_link
import time
from scripts.deploy_lottery import deploy_lottery

def test_can_pick_winner():
if network.show_active() in LOCAL_BLOCKCHAIN_ENVIRONMENTS:
pytest.skip()
lottery = deploy_lottery()
account = get_account()
lottery.startLottery({'from': account})
lottery.enter({'from':account, 'value': lottery.getEntranceFee()})
lottery.enter({'from':account, 'value': lottery.getEntranceFee()})
fund_with_link(lottery)
lottery.endLottery({'from': account})
time.sleep(130)
assert lottery.recentWinner() == account
assert lottery.balance() == 0
67 changes: 67 additions & 0 deletions smart-contract-lottery/tests/test_lottery_unit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from brownie import Lottery,accounts, config, network, exceptions
from scripts.deploy_lottery import deploy_lottery
from scripts.helpers import LOCAL_BLOCKCHAIN_ENVIRONMENTS, get_account, fund_with_link, get_contract
from web3 import Web3
import pytest

def test_get_entrance_fee():
if network.show_active() not in LOCAL_BLOCKCHAIN_ENVIRONMENTS:
pytest.skip()
# Arrange
lottery = deploy_lottery()
# Act
# 50/4460 =
expected_entrance_fee = Web3.toWei(0.025, 'ether')
print(f"exp fee: {Web3.fromWei(expected_entrance_fee, 'ether')}")
entrance_fee = lottery.getEntranceFee()
print(f"ent fee: {Web3.fromWei(entrance_fee, 'ether')}")
#Assert
assert expected_entrance_fee == entrance_fee

def test_cant_enter_unless_started():
if network.show_active() not in LOCAL_BLOCKCHAIN_ENVIRONMENTS:
pytest.skip()
lottery = deploy_lottery()
with pytest.raises(exceptions.VirtualMachineError):
lottery.enter({'from':get_account(), 'value': lottery.getEntranceFee()})

def test_can_start_and_enter_lottery():
if network.show_active() not in LOCAL_BLOCKCHAIN_ENVIRONMENTS:
pytest.skip()
lottery = deploy_lottery()
account = get_account()
lottery.startLottery({'from': account})
lottery.enter({'from':account, 'value': lottery.getEntranceFee()})
assert lottery.players(0) == account

def test_can_end_lottery():
if network.show_active() not in LOCAL_BLOCKCHAIN_ENVIRONMENTS:
pytest.skip()
lottery = deploy_lottery()
account = get_account()
lottery.startLottery({'from': account})
lottery.enter({'from': account, 'value': lottery.getEntranceFee()})
fund_with_link(lottery)
lottery.endLottery({'from': account})
assert lottery.lottery_state() == 2

def test_can_pick_winner_correctly():
if network.show_active() not in LOCAL_BLOCKCHAIN_ENVIRONMENTS:
pytest.skip()
lottery = deploy_lottery()
account = get_account()
lottery.startLottery({'from': account})
lottery.enter({'from': account, 'value': lottery.getEntranceFee()})
lottery.enter({'from': get_account(index=1), 'value': lottery.getEntranceFee()})
lottery.enter({'from': get_account(index = 2), 'value': lottery.getEntranceFee()})
fund_with_link(lottery)
transaction = lottery.endLottery({'from': account})
request_id = transaction.events['RequestedRandomness']['requestId']
STATIC_RNG = 777
get_contract('vrf_coordinator').callBackWithRandomness(request_id, STATIC_RNG, lottery.address, {'from': account})
starting_balance_of_account = account.balance()
balance_of_lottery = lottery.balance()
# 777 % 3 = 0 - account will be the winner
assert lottery.recentWinner() == account
assert lottery.balance() == 0
assert account.balance() == starting_balance_of_account + balance_of_lottery

0 comments on commit 6587612

Please sign in to comment.