Skip to content

Commit

Permalink
fixed function selectors on dynamic arrays, added scripts to "see" th…
Browse files Browse the repository at this point in the history
…e whole process end to end
  • Loading branch information
PatrickAlphaC committed Aug 3, 2022
1 parent 1f313bb commit 1df2ff9
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 7 deletions.
74 changes: 74 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ It shows how to use the these frameworks and languages as well as the following
- [Deploy to a local or adhoc network](#deploy-to-a-local-or-adhoc-network)
- [Deploy to a mainnet or test network](#deploy-to-a-mainnet-or-test-network)
- [Interacting with Contracts](#interacting-with-contracts)
- [Price Feed Consumer](#price-feed-consumer-1)
- [VRF Consumer](#vrf-consumer)
- [Keeper Consumer](#keeper-consumer)
- [Miscellaneous](#miscellaneous)
- [Contributing](#contributing)
- [Resources](#resources)
Expand Down Expand Up @@ -189,6 +192,77 @@ To interact with contracts, we recommend using the console.
ape console --network ethereum:rinkeby:alchemy
```

Or, you can follow along and run the scripts to see the end-to-end functionaltiy.

#### Price Feed Consumer

1. Deploy the contract

```
ape run scripts/deploy_price_feed_consumer.py --network ethereum:rinkeby:alchemy
```

2. Read it

```
ape run scripts/read_price_feed.py --network ethereum:rinkeby:alchemy
```



#### VRF Consumer

1. Create subscription and fund it with LINK.

You can do that with the script, or going to the UI at [vrf.chain.link](https://vrf.chain.link)

```
ape run scripts/create_subscription.py --network ethereum:rinkeby:alchemy
```

2. Update your `helper_config.py` with your subscription Id.

3. Deploy vrf consumer

```
ape run scripts/deploy_vrf_consumer.py --network ethereum:rinkeby:alchemy
```

4. [Add your contract/consumer to the VRF UI](https://docs.chain.link/docs/get-a-random-number/#create-and-fund-a-subscription)


5. Request a random number and wait for a response


```
ape run scripts/request_and_read_randomness.py --network ethereum:rinkeby:alchemy
```

#### Keeper Consumer

1. Deploy the contract

```
ape run scripts/deploy_keepers_consumer.py --network ethereum:rinkeby:alchemy
```

2. Register your upkeep on the Keepers UI

You can go to [keepers.chain.link](https://keepers.chain.link/new-custom-logic)

3. Watch for your counter to automatically start going up!

After a delay, run:

```
ape run scripts/read_counter.py --network ethereum:rinkeby:alchemy
```

And it should be updated!




# Miscellaneous

1. Testing and forking is a bit tricky at the moment.
Expand Down
2 changes: 1 addition & 1 deletion contracts/KeepersConsumer.vy
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def __init__(update_interval: uint256):

@external
@view
def checkUpkeep(checkData: Bytes[1]) -> (bool, Bytes[1]):
def checkUpkeep(checkData: Bytes[32]) -> (bool, Bytes[32]):
upkeep_needed: bool = (block.timestamp - self.last_time_stamp) > INTERVAL
return(upkeep_needed, b"\x00")

Expand Down
17 changes: 12 additions & 5 deletions contracts/VRFConsumerV2.vy
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import interfaces.VRFCoordinatorV2 as VRFCoordinatorV2

NUM_WORDS: constant(uint32) = 1
MAX_ARRAY_SIZE: constant(uint256) = 10
REQUEST_CONFIRMATIONS: constant(uint16) = 3
CALLBACK_GAS_LIMIT: constant(uint32) = 100000

Expand Down Expand Up @@ -31,13 +32,19 @@ def request_random_words():
)

@internal
def fulfillRandomWords(request_id: uint256, _random_words: uint256[NUM_WORDS]):
self.random_words = _random_words
log ReturnedRandomness(_random_words)
def fulfillRandomWords(request_id: uint256, _random_words: DynArray[uint256, MAX_ARRAY_SIZE]):
self.random_words = [_random_words[0]]
log ReturnedRandomness(self.random_words)

# In solidity, this is the equivalent of inheriting the VRFConsumerBaseV2
# Vyper doesn't have inheritance, so we just add the function here
# Also, we need to use `DynArray` so our function selector is the same as the one Chainlink VRF is looking for:
# Function Signature: rawFulfillRandomWords(uint256,uint256[])
# Function selector: 0x1fe543e3
@external
def rawFulfillRandomWords(requestId: uint256, randomWords: uint256[NUM_WORDS]):
def rawFulfillRandomWords(requestId: uint256, randomWords: DynArray[uint256, MAX_ARRAY_SIZE]):
assert msg.sender == self.vrf_coordinator.address, "Only coordinator can fulfill!"
self.fulfillRandomWords(requestId, randomWords)
myBytes: Bytes[4] = b"\x00"
myString: String[4] = convert(myBytes, String[4])
self.fulfillRandomWords(requestId, randomWords)

2 changes: 2 additions & 0 deletions scripts/create_subscription.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ def create_subscription():

def fund_subscription(subscription_id=1):
print("Funding subscription...")
ecosystem = networks.active_provider.network.ecosystem.name
chain_name = networks.active_provider.network.name
account = get_account()
fund_amount = network_config[ecosystem][chain_name].get("fund_amount", False)
link_token = get_or_deploy_contract("LinkToken")
Expand Down
2 changes: 1 addition & 1 deletion scripts/helper_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"fund_amount": 5_000000000000000000,
},
"rinkeby": {
"subscription_id": 0, # Add your own subscription Id here!
"subscription_id": 9757, # Add your own subscription Id here!
"key_hash": "0xd89b2bf150e3b9e13446986e571fb9cab24b13cea0a43ea20a6049a85cc807cc",
"update_interval": 60,
"fund_amount": 5_000000000000000000,
Expand Down
17 changes: 17 additions & 0 deletions scripts/read_counter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from ape import project, accounts, networks
from scripts.helper_functions import get_account, get_or_deploy_contract


def read_counter():
account = get_account()
ecosystem = networks.active_provider.network.ecosystem.name
chain_name = networks.active_provider.network.name

keepers_consumer = project.KeepersConsumer.deployments[-1]
response = keepers_consumer.counter()
print(f"The current count is {response}")
return keepers_consumer


def main():
read_counter()
17 changes: 17 additions & 0 deletions scripts/read_price_feed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from ape import project, accounts, networks
from scripts.helper_functions import get_account, get_or_deploy_contract


def read_price_feed():
account = get_account()
ecosystem = networks.active_provider.network.ecosystem.name
chain_name = networks.active_provider.network.name

price_feed_consumer = project.PriceConsumer.deployments[-1]
response = price_feed_consumer.get_latest_price()
print(f"The current price of ETH is {response}")
return price_feed_consumer


def main():
read_price_feed()
38 changes: 38 additions & 0 deletions scripts/request_and_read_randomness.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from ape import project, accounts, networks
from scripts.helper_functions import get_account, get_or_deploy_contract
import time


def request_and_read_randomness():
account = get_account()
ecosystem = networks.active_provider.network.ecosystem.name
chain_name = networks.active_provider.network.name

vrf_consumer = project.VRConsumerV2.deployments[-1]
request_tx = vrf_consumer.request_random_words(sender=account)

print("Request sent! Let's wait for a response...")

randomness = wait_for_randomness(vrf_consumer)
if randomness:
print(f"The random number was {randomness}")
else:
print("No random number found")


def wait_for_randomness(vrf_consumer, timeout=200, poll_interval=2):
print("Waiting for random response...")
start_time = time.time()
current_time = time.time()
while current_time - start_time < timeout:
response = vrf_consumer.random_words(0)
if response > 0:
return response
time.sleep(poll_interval)
current_time = time.time()
print("Done waiting!")
return None


def main():
request_and_read_randomness()

0 comments on commit 1df2ff9

Please sign in to comment.