Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VRF-391: change consumer contract for CTF test #8680

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func SetAndGetOCR2VRFPluginConfig(t *testing.T, nonBootstrapNodes []*client.Chai
return ocr2VRFPluginConfig
}

func FundVRFCoordinatorSubscription(t *testing.T, linkToken contracts.LinkToken, coordinator contracts.VRFCoordinatorV3, chainClient blockchain.EVMClient, subscriptionID, linkFundingAmount *big.Int) {
func FundVRFCoordinatorV3Subscription(t *testing.T, linkToken contracts.LinkToken, coordinator contracts.VRFCoordinatorV3, chainClient blockchain.EVMClient, subscriptionID, linkFundingAmount *big.Int) {
encodedSubId, err := chainlinkutils.ABIEncode(`[{"type":"uint256"}]`, subscriptionID)
require.NoError(t, err, "Error Abi encoding subscriptionID")
_, err = linkToken.TransferAndCall(coordinator.Address(), big.NewInt(0).Mul(linkFundingAmount, big.NewInt(1e18)), encodedSubId)
Expand Down Expand Up @@ -212,7 +212,7 @@ func RequestAndRedeemRandomness(
err = chainClient.WaitForEvents()
require.NoError(t, err, "Error waiting for TXs to complete")

requestID := getRequestId(t, consumer, receipt, confirmationDelay, subscriptionID)
requestID := getRequestId(t, consumer, receipt, confirmationDelay)

newTransmissionEvent, err := vrfBeacon.WaitForNewTransmissionEvent(time.Minute * 5)
require.NoError(t, err, "Error waiting for NewTransmission event from VRF Beacon Contract")
Expand Down Expand Up @@ -249,7 +249,7 @@ func RequestRandomnessFulfillment(
err = chainClient.WaitForEvents()
require.NoError(t, err, "Error waiting for TXs to complete")

requestID := getRequestId(t, consumer, receipt, confirmationDelay, subscriptionID)
requestID := getRequestId(t, consumer, receipt, confirmationDelay)

newTransmissionEvent, err := vrfBeacon.WaitForNewTransmissionEvent(time.Minute * 5)
require.NoError(t, err, "Error waiting for NewTransmission event from VRF Beacon Contract")
Expand All @@ -261,7 +261,7 @@ func RequestRandomnessFulfillment(
return requestID
}

func getRequestId(t *testing.T, consumer contracts.VRFBeaconConsumer, receipt *types.Receipt, confirmationDelay, subscriptionID *big.Int) *big.Int {
func getRequestId(t *testing.T, consumer contracts.VRFBeaconConsumer, receipt *types.Receipt, confirmationDelay *big.Int) *big.Int {
periodBlocks, err := consumer.IBeaconPeriodBlocks(nil)
require.NoError(t, err, "Error getting Beacon Period block count")

Expand Down Expand Up @@ -329,7 +329,7 @@ func SetupOCR2VRFUniverse(
require.NoError(t, err, "Error waiting for TXs to complete")

//3. fund subscription with LINK token
FundVRFCoordinatorSubscription(
FundVRFCoordinatorV3Subscription(
t,
linkToken,
coordinatorContract,
Expand Down
10 changes: 10 additions & 0 deletions integration-tests/actions/vrfv2_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package actions
import (
"context"
"fmt"
chainlinkutils "github.com/smartcontractkit/chainlink/core/utils"
"math/big"
"testing"

Expand Down Expand Up @@ -107,3 +108,12 @@ func VRFV2RegisterProvingKey(
require.NoError(t, err, "Error registering proving keys")
return provingKey
}

func FundVRFCoordinatorV2Subscription(t *testing.T, linkToken contracts.LinkToken, coordinator contracts.VRFCoordinatorV2, chainClient blockchain.EVMClient, subscriptionID uint64, linkFundingAmount *big.Int) {
encodedSubId, err := chainlinkutils.ABIEncode(`[{"type":"uint64"}]`, subscriptionID)
require.NoError(t, err, "Error Abi encoding subscriptionID")
_, err = linkToken.TransferAndCall(coordinator.Address(), big.NewInt(0).Mul(linkFundingAmount, big.NewInt(1e18)), encodedSubId)
require.NoError(t, err, "Error sending Link token")
err = chainClient.WaitForEvents()
require.NoError(t, err, "Error waiting for TXs to complete")
}
1 change: 1 addition & 0 deletions integration-tests/contracts/contract_deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ type ContractDeployer interface {
DeployUpkeepPerformCounterRestrictive(testRange *big.Int, averageEligibilityCadence *big.Int) (UpkeepPerformCounterRestrictive, error)
DeployVRFConsumer(linkAddr string, coordinatorAddr string) (VRFConsumer, error)
DeployVRFConsumerV2(linkAddr string, coordinatorAddr string) (VRFConsumerV2, error)
DeployVRFv2Consumer(coordinatorAddr string) (VRFv2Consumer, error)
DeployVRFCoordinator(linkAddr string, bhsAddr string) (VRFCoordinator, error)
DeployVRFCoordinatorV2(linkAddr string, bhsAddr string, linkEthFeedAddr string) (VRFCoordinatorV2, error)
DeployDKG() (DKG, error)
Expand Down
14 changes: 14 additions & 0 deletions integration-tests/contracts/contract_vrf_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ type VRFCoordinatorV2 interface {
publicProvingKey [2]*big.Int,
) error
HashOfKey(ctx context.Context, pubKey [2]*big.Int) ([32]byte, error)
CreateSubscription() error
AddConsumer(subId uint64, consumerAddress string) error
Address() string
}

Expand All @@ -66,6 +68,13 @@ type VRFConsumerV2 interface {
Fund(ethAmount *big.Float) error
}

type VRFv2Consumer interface {
Address() string
RequestRandomness(hash [32]byte, subID uint64, confs uint16, gasLimit uint32, numWords uint32) error
GetRequestStatus(ctx context.Context, requestID *big.Int) (RequestStatus, error)
GetLastRequestId(ctx context.Context) (*big.Int, error)
}

type DKG interface {
Address() string
AddClient(keyID string, clientAddress string) error
Expand Down Expand Up @@ -132,3 +141,8 @@ type VRFBeaconConsumer interface {
type BatchBlockhashStore interface {
Address() string
}

type RequestStatus struct {
Fulfilled bool
RandomWords []*big.Int
}
1,045 changes: 1,045 additions & 0 deletions integration-tests/contracts/ethereum/VRFv2Consumer.go

Large diffs are not rendered by default.

91 changes: 91 additions & 0 deletions integration-tests/contracts/ethereum/src/VRFv2Consumer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// SPDX-License-Identifier: MIT
// An example of a consumer contract that relies on a subscription for funding.
pragma solidity ^0.8.7;

import "../../../../../contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "../../../../../contracts/src/v0.8/VRFConsumerBaseV2.sol";
import "../../../../../contracts/src/v0.8/ConfirmedOwner.sol";

/**
* THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY.
* THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.
* DO NOT USE THIS CODE IN PRODUCTION.
*/

contract VRFv2Consumer is VRFConsumerBaseV2, ConfirmedOwner {
event RequestSent(uint256 requestId, uint32 numWords);
event RequestFulfilled(uint256 requestId, uint256[] randomWords);

struct RequestStatus {
bool fulfilled; // whether the request has been successfully fulfilled
bool exists; // whether a requestId exists
uint256[] randomWords;
}
mapping(uint256 => RequestStatus)
public s_requests; /* requestId --> requestStatus */
VRFCoordinatorV2Interface COORDINATOR;

// past requests Id.
uint256[] public requestIds;
uint256 public lastRequestId;

constructor(
address vrfCoordinator
)
VRFConsumerBaseV2(vrfCoordinator)
ConfirmedOwner(msg.sender)
{
COORDINATOR = VRFCoordinatorV2Interface(
vrfCoordinator
);
}

// Assumes the subscription is funded sufficiently.
function requestRandomWords(
uint64 subId,
uint32 callbackGasLimit,
uint16 requestConfirmations,
uint32 numWords,
bytes32 keyHash
)
external
onlyOwner
returns (uint256 requestId)
{
// Will revert if subscription is not set and funded.
requestId = COORDINATOR.requestRandomWords(
keyHash,
subId,
requestConfirmations,
callbackGasLimit,
numWords
);
s_requests[requestId] = RequestStatus({
randomWords: new uint256[](0),
exists: true,
fulfilled: false
});
requestIds.push(requestId);
lastRequestId = requestId;
emit RequestSent(requestId, numWords);
return requestId;
}

function fulfillRandomWords(
uint256 _requestId,
uint256[] memory _randomWords
) internal override {
require(s_requests[_requestId].exists, "request not found");
s_requests[_requestId].fulfilled = true;
s_requests[_requestId].randomWords = _randomWords;
emit RequestFulfilled(_requestId, _randomWords);
}

function getRequestStatus(
uint256 _requestId
) external view returns (bool fulfilled, uint256[] memory randomWords) {
require(s_requests[_requestId].exists, "request not found");
RequestStatus memory request = s_requests[_requestId];
return (request.fulfilled, request.randomWords);
}
}
110 changes: 110 additions & 0 deletions integration-tests/contracts/ethereum_vrf_contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/hex"
"fmt"
int_ethereum "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum"
"math/big"
"time"

Expand Down Expand Up @@ -132,6 +133,23 @@ func (e *EthereumContractDeployer) DeployVRFConsumerV2(linkAddr string, coordina
}, err
}

func (e *EthereumContractDeployer) DeployVRFv2Consumer(coordinatorAddr string) (VRFv2Consumer, error) {
address, _, instance, err := e.client.DeployContract("VRFv2Consumer", func(
auth *bind.TransactOpts,
backend bind.ContractBackend,
) (common.Address, *types.Transaction, interface{}, error) {
return int_ethereum.DeployVRFv2Consumer(auth, backend, common.HexToAddress(coordinatorAddr))
})
if err != nil {
return nil, err
}
return &EthereumVRFv2Consumer{
client: e.client,
consumer: instance.(*int_ethereum.VRFv2Consumer),
address: address,
}, err
}

// DeployDKG deploys DKG contract
func (e *EthereumContractDeployer) DeployDKG() (DKG, error) {
address, _, instance, err := e.client.DeployContract("DKG", func(
Expand Down Expand Up @@ -327,6 +345,18 @@ func (v *EthereumVRFCoordinatorV2) RegisterProvingKey(
return v.client.ProcessTransaction(tx)
}

func (v *EthereumVRFCoordinatorV2) CreateSubscription() error {
opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet())
if err != nil {
return err
}
tx, err := v.coordinator.CreateSubscription(opts)
if err != nil {
return err
}
return v.client.ProcessTransaction(tx)
}

// EthereumVRFCoordinator represents VRF coordinator contract
type EthereumVRFCoordinator struct {
address *common.Address
Expand Down Expand Up @@ -376,6 +406,13 @@ type EthereumVRFConsumerV2 struct {
consumer *ethereum.VRFConsumerV2
}

// EthereumVRFv2Consumer represents VRFv2 consumer contract
type EthereumVRFv2Consumer struct {
address *common.Address
client blockchain.EVMClient
consumer *int_ethereum.VRFv2Consumer
}

// CurrentSubscription get current VRFv2 subscription
func (v *EthereumVRFConsumerV2) CurrentSubscription() (uint64, error) {
return v.consumer.SSubId(&bind.CallOpts{
Expand Down Expand Up @@ -414,6 +451,10 @@ func (v *EthereumVRFConsumerV2) Address() string {
return v.address.Hex()
}

func (v *EthereumVRFv2Consumer) Address() string {
return v.address.Hex()
}

// GasAvailable get available gas after randomness fulfilled
func (v *EthereumVRFConsumerV2) GasAvailable() (*big.Int, error) {
return v.consumer.SGasAvailable(&bind.CallOpts{
Expand All @@ -436,6 +477,33 @@ func (v *EthereumVRFConsumerV2) RequestRandomness(hash [32]byte, subID uint64, c
if err != nil {
return err
}
log.Info().Interface("Sub ID", subID).
Interface("Number of Words", numWords).
Interface("Number of Confirmations", confs).
Interface("Callback Gas Limit", gasLimit).
Interface("KeyHash", hex.EncodeToString(hash[:])).
Interface("Consumer Contract", v.address).
Msg("RequestRandomness called")
return v.client.ProcessTransaction(tx)
}

// RequestRandomness request VRFv2 random words
func (v *EthereumVRFv2Consumer) RequestRandomness(hash [32]byte, subID uint64, confs uint16, gasLimit uint32, numWords uint32) error {
opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet())
if err != nil {
return err
}
tx, err := v.consumer.RequestRandomWords(opts, subID, gasLimit, confs, numWords, hash)
if err != nil {
return err
}
log.Info().Interface("Sub ID", subID).
Interface("Number of Words", numWords).
Interface("Number of Confirmations", confs).
Interface("Callback Gas Limit", gasLimit).
Interface("KeyHash", hex.EncodeToString(hash[:])).
Interface("Consumer Contract", v.address).
Msg("RequestRandomness called")
return v.client.ProcessTransaction(tx)
}

Expand All @@ -447,6 +515,20 @@ func (v *EthereumVRFConsumerV2) RandomnessOutput(ctx context.Context, arg0 *big.
}, arg0)
}

func (v *EthereumVRFv2Consumer) GetRequestStatus(ctx context.Context, requestID *big.Int) (RequestStatus, error) {
return v.consumer.GetRequestStatus(&bind.CallOpts{
From: common.HexToAddress(v.client.GetDefaultWallet().Address()),
Context: ctx,
}, requestID)
}

func (v *EthereumVRFv2Consumer) GetLastRequestId(ctx context.Context) (*big.Int, error) {
return v.consumer.LastRequestId(&bind.CallOpts{
From: common.HexToAddress(v.client.GetDefaultWallet().Address()),
Context: ctx,
})
}

// GetAllRandomWords get all VRFv2 randomness output words
func (v *EthereumVRFConsumerV2) GetAllRandomWords(ctx context.Context, num int) ([]*big.Int, error) {
words := make([]*big.Int, 0)
Expand Down Expand Up @@ -824,6 +906,22 @@ func (coordinator *EthereumVRFCoordinatorV3) FindSubscriptionID() (*big.Int, err
return subscriptionIterator.Event.SubId, nil
}

func (coordinator *EthereumVRFCoordinatorV2) AddConsumer(subId uint64, consumerAddress string) error {
opts, err := coordinator.client.TransactionOpts(coordinator.client.GetDefaultWallet())
if err != nil {
return err
}
tx, err := coordinator.coordinator.AddConsumer(
opts,
subId,
common.HexToAddress(consumerAddress),
)
if err != nil {
return err
}
return coordinator.client.ProcessTransaction(tx)
}

func (coordinator *EthereumVRFCoordinatorV3) AddConsumer(subId *big.Int, consumerAddress string) error {
opts, err := coordinator.client.TransactionOpts(coordinator.client.GetDefaultWallet())
if err != nil {
Expand Down Expand Up @@ -986,6 +1084,10 @@ func (consumer *EthereumVRFBeaconConsumer) RequestRandomness(
if err != nil {
return nil, errors.Wrap(err, "GetTxReceipt failed")
}
log.Info().Interface("Sub ID", subID).
Interface("Number of Words", numWords).
Interface("Number of Confirmations", confirmationDelayArg).
Msg("RequestRandomness called")
return receipt, nil
}

Expand All @@ -1004,6 +1106,9 @@ func (consumer *EthereumVRFBeaconConsumer) RedeemRandomness(
if err != nil {
return err
}
log.Info().Interface("Sub ID", subID).
Interface("Request ID", requestID).
Msg("RedeemRandomness called")
return consumer.client.ProcessTransaction(tx)
}

Expand Down Expand Up @@ -1041,6 +1146,11 @@ func (consumer *EthereumVRFBeaconConsumer) RequestRandomnessFulfillment(
if err != nil {
return nil, errors.Wrap(err, "GetTxReceipt failed")
}
log.Info().Interface("Sub ID", subID).
Interface("Number of Words", numWords).
Interface("Number of Confirmations", confirmationDelayArg).
Interface("Callback Gas Limit", callbackGasLimit).
Msg("RequestRandomnessFulfillment called")
return receipt, nil
}

Expand Down
Loading