Skip to content

Commit

Permalink
Merge pull request #3 from codenamejason/jax/test-updates
Browse files Browse the repository at this point in the history
Add Tests
  • Loading branch information
codenamejason committed Oct 29, 2023
2 parents e3ea83f + 5926e5e commit 9534cb0
Show file tree
Hide file tree
Showing 36 changed files with 2,443 additions and 65 deletions.
Binary file added .DS_Store
Binary file not shown.
4 changes: 3 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ jobs:
strategy:
fail-fast: true

name: Foundry project
name: Will4USNFT Foundry project
runs-on: ubuntu-latest
env:
ARBITRUM_GOERLI_RPC_URL: ${{ secrets.ARBITRUM_GOERLI_RPC_URL }}
steps:
- uses: actions/checkout@v3
with:
Expand Down
9 changes: 9 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,12 @@
[submodule "lib/openzeppelin-contracts"]
path = lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
[submodule "lib/chainlink"]
path = lib/chainlink
url = https://github.com/smartcontractkit/chainlink
[submodule "lib/solady"]
path = lib/solady
url = https://github.com/vectorized/solady
[submodule "lib/eas-contracts"]
path = lib/eas-contracts
url = https://github.com/ethereum-attestation-service/eas-contracts
43 changes: 43 additions & 0 deletions DEPLOYMENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Will4Us NFT Deployments

## Arbitrum Mainnet

| Contract | Address | Link |
| --- | --- | --- |
| Will4UsNFT | 0x0 | [LINK](https://goerli.arbiscan.io/address/0x0) |

## Arbitrum Testnet

| Contract | Address | Link |
| --- | --- | --- |
| Will4UsNFT | 0xe2e1f1c872842350c85623c2323914fd24a6c17c | [LINK](https://goerli.arbiscan.io/address/0xe2e1f1c872842350c85623c2323914fd24a6c17c) |

## Goerli Testnet

| Contract | Address | Link |
| --- | --- | --- |
| Will4UsNFT | 0x0 | [LINK](https://goerli.etherscan.io/address/0x0) |

## Base Goerli

| Contract | Address | Link |
| --- | --- | --- |
| Will4UsNFT | 0x0 | [LINK](https://basescan.org/address/0x0) |

## Base Mainnet

| Contract | Address | Link |
| --- | --- | --- |
| Will4UsNFT | 0x0 | [LINK](https://basescan.org/address/0x0) |

## Optimism Goerli

| Contract | Address | Link |
| --- | --- | --- |
| Will4UsNFT | 0x0 | [LINK](https://optimistic.etherscan.io/address/0x0) |

## Optimism Mainnet

| Contract | Address | Link |
| --- | --- | --- |
| Will4UsNFT | 0x0 | [LINK](https://optimistic.etherscan.io/address/0x0) |
33 changes: 33 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,38 @@
src = "src"
out = "out"
libs = ["lib"]
broadcast = "broadcast"

[rpc_endpoints]
arbitrumGoerli = "${ARBITRUM_GOERLI_RPC_URL}"

[etherscan]
arbitrumGoerli = { key = "${ARBITRUM_API_KEY}" }


[fuzz]
runs = 256
max_test_rejects = 65536
seed = '0x3e8'
dictionary_weight = 40
include_storage = true
include_push_bytes = true

[invariant]
runs = 256
depth = 15
fail_on_revert = false
call_override = false
dictionary_weight = 80
include_storage = true
include_push_bytes = true
shrink_sequence = true

[fmt]
line_length = 100
tab_width = 4
bracket_spacing = true

# Remappings in remappings.txt

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
1 change: 1 addition & 0 deletions lib/chainlink
Submodule chainlink added at b96cb8
1 change: 1 addition & 0 deletions lib/eas-contracts
Submodule eas-contracts added at 9df0f7
1 change: 1 addition & 0 deletions lib/solady
Submodule solady added at 22fa9a
2 changes: 2 additions & 0 deletions remappings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ ds-test/=lib/forge-std/lib/ds-test/src/
erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/
forge-std/=lib/forge-std/src/
openzeppelin-contracts/=lib/openzeppelin-contracts/
@chainlink/=lib/chainlink/contracts/
eas-contracts/=lib/eas-contracts/contracts/
13 changes: 8 additions & 5 deletions script/Will4USNFT.s.sol
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.20;

import {Script} from "forge-std/Script.sol";
import { Script } from "forge-std/Script.sol";
// import { Test, console2 } from "forge-std/Test.sol";

import {Will4USNFT} from "../src/Will4USNFT.sol";
import { Will4USNFT } from "../src/Will4USNFT.sol";

/// @notice This script is used to deploy the Will4USNFT contract
/// @dev Use this to run
/// 'source .env' if you are using a .env file for your rpc-url
/// 'forge script script/Will4USNFT.s.sol:Will4USNFTScript --rpc-url $GOERLI_RPC_URL --broadcast --verify -vvvv'
contract Will4USNFTScript is Script {
function setUp() public {}
function setUp() public { }

function run() public {
uint256 deployerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY");
address deployerAddress = vm.envAddress("DEPLOYER_ADDRESS");
// string memory url = vm.rpcUrl("arbitrumGoerli");
// assertEq(url, "https://arb-goerli.g.alchemy.com/v2/RqTiyvS7OspxaAQUQupKKCTjmf94JL-I");
vm.startBroadcast(deployerPrivateKey);

Will4USNFT nftContract = new Will4USNFT(deployerAddress);
new Will4USNFT(deployerAddress, deployerAddress, deployerAddress, 5);

nftContract.awardCampaignItem(deployerAddress, "https://placeholder.com/1", 1);
// nftContract.awardCampaignItem(deployerAddress, 1);

vm.stopBroadcast();
}
Expand Down
86 changes: 86 additions & 0 deletions src/APIConsumer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import "@chainlink/src/v0.8/ChainlinkClient.sol";
import "@chainlink/src/v0.8/shared/access/ConfirmedOwner.sol";

/**
* @title The APIConsumer contract
* @notice An API Consumer contract that makes GET requests
*/
contract APIConsumer is ChainlinkClient, ConfirmedOwner {
using Chainlink for Chainlink.Request;

bytes32 private jobId;
uint256 private fee;

mapping(address => bool) public isKYCApproved;

event DataFullfilled(bytes32 requestId, bool isKYCApproved);

/**
* @notice Initialize the link token and target oracle
*
* Sepolia Testnet details:
* Link Token: 0x779877A7B0D9E8603169DdbD7836e478b4624789
* Oracle: 0x6090149792dAAeE9D1D568c9f9a6F6B46AA29eFD (Chainlink DevRel)
* jobId: ca98366cc7314957b8c012c72f05aeeb
*
*/
constructor() ConfirmedOwner(msg.sender) {
setChainlinkToken(0x779877A7B0D9E8603169DdbD7836e478b4624789);
setChainlinkOracle(0x6090149792dAAeE9D1D568c9f9a6F6B46AA29eFD);
jobId = "ca98366cc7314957b8c012c72f05aeeb";
fee = (1 * LINK_DIVISIBILITY) / 10; // 0,1 * 10**18 (Varies by network and job)
}
/**
* @notice Creates a Chainlink request to retrieve API response and update the mapping
*
* @return requestId - ID of the request
*/

function requestKYCData() public returns (bytes32 requestId) {
Chainlink.Request memory request =
buildChainlinkRequest(jobId, address(this), this.fulfill.selector);

// Set the URL to perform the GET request on
request.add("get", "set url here");

// Set the path to find the desired data in the API response, where the response format is:
// {"RAW":
// {"ETH":
// {"USD":
// {
// "VOLUME24HOUR": xxx.xxx,
// }
// }
// }
// }
// Chainlink node versions prior to 1.0.0 supported this format
// request.add("path", "RAW.ETH.USD.VOLUME24HOUR");
request.add("path", "");

// Sends the request
return sendChainlinkRequest(request, fee);
}

/**
* Receive the response in the form of uint256
*/
function fulfill(bytes32 _requestId, bool _isKYCApproved)
public
recordChainlinkFulfillment(_requestId)
{
isKYCApproved[address(0)] = _isKYCApproved;

emit DataFullfilled(_requestId, _isKYCApproved);
}

/**
* Allow withdraw of Link tokens from the contract
*/
function withdrawLink() public onlyOwner {
LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress());
require(link.transfer(msg.sender, link.balanceOf(address(this))), "Unable to transfer");
}
}
97 changes: 97 additions & 0 deletions src/FunctionConsumer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import { FunctionsClient } from "@chainlink/src/v0.8/functions/dev/1_0_0/FunctionsClient.sol";
import { ConfirmedOwner } from "@chainlink/src/v0.8/shared/access/ConfirmedOwner.sol";
import { FunctionsRequest } from
"@chainlink/src/v0.8/functions/dev/1_0_0/libraries/FunctionsRequest.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 FunctionsConsumer is FunctionsClient, ConfirmedOwner {
using FunctionsRequest for FunctionsRequest.Request;

bytes32 public s_lastRequestId;
bytes public s_lastResponse;
bytes public s_lastError;

error UnexpectedRequestID(bytes32 requestId);

event Response(bytes32 indexed requestId, bytes response, bytes err);

constructor(address router) FunctionsClient(router) ConfirmedOwner(msg.sender) { }

/**
* @notice Send a simple request
* @param source JavaScript source code
* @param encryptedSecretsUrls Encrypted URLs where to fetch user secrets
* @param donHostedSecretsSlotID Don hosted secrets slotId
* @param donHostedSecretsVersion Don hosted secrets version
* @param args List of arguments accessible from within the source code
* @param bytesArgs Array of bytes arguments, represented as hex strings
* @param subscriptionId Billing ID
*/
function sendRequest(
string memory source,
bytes memory encryptedSecretsUrls,
uint8 donHostedSecretsSlotID,
uint64 donHostedSecretsVersion,
string[] memory args,
bytes[] memory bytesArgs,
uint64 subscriptionId,
uint32 gasLimit,
bytes32 jobId
) external onlyOwner returns (bytes32 requestId) {
FunctionsRequest.Request memory req;
req.initializeRequestForInlineJavaScript(source);
if (encryptedSecretsUrls.length > 0) {
req.addSecretsReference(encryptedSecretsUrls);
} else if (donHostedSecretsVersion > 0) {
req.addDONHostedSecrets(donHostedSecretsSlotID, donHostedSecretsVersion);
}
if (args.length > 0) req.setArgs(args);
if (bytesArgs.length > 0) req.setBytesArgs(bytesArgs);
s_lastRequestId = _sendRequest(req.encodeCBOR(), subscriptionId, gasLimit, jobId);
return s_lastRequestId;
}

/**
* @notice Send a pre-encoded CBOR request
* @param request CBOR-encoded request data
* @param subscriptionId Billing ID
* @param gasLimit The maximum amount of gas the request can consume
* @param jobId ID of the job to be invoked
* @return requestId The ID of the sent request
*/
function sendRequestCBOR(
bytes memory request,
uint64 subscriptionId,
uint32 gasLimit,
bytes32 jobId
) external onlyOwner returns (bytes32 requestId) {
s_lastRequestId = _sendRequest(request, subscriptionId, gasLimit, jobId);
return s_lastRequestId;
}

/**
* @notice Store latest result/error
* @param requestId The request ID, returned by sendRequest()
* @param response Aggregated response from the user code
* @param err Aggregated error from the user code or from the execution pipeline
* Either response or error parameter will be set, but never both
*/
function fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err)
internal
override
{
if (s_lastRequestId != requestId) {
revert UnexpectedRequestID(requestId);
}
s_lastResponse = response;
s_lastError = err;
emit Response(requestId, s_lastResponse, s_lastError);
}
}
Loading

0 comments on commit 9534cb0

Please sign in to comment.