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

Enable cross-chain authorizers #1488

Merged
merged 18 commits into from
Oct 19, 2022
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
9 changes: 9 additions & 0 deletions .changeset/wild-walls-beg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@api3/airnode-deployer': minor
'@api3/airnode-examples': minor
'@api3/airnode-node': minor
'@api3/airnode-operation': minor
'@api3/airnode-validator': minor
---

Enable cross-chain authorizers
3 changes: 2 additions & 1 deletion packages/airnode-deployer/config/config.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
{
"maxConcurrency": 100,
"authorizers": {
"requesterEndpointAuthorizers": []
"requesterEndpointAuthorizers": [],
"crossChainRequesterAuthorizers": []
},
"authorizations": {
"requesterEndpointAuthorizations": {}
Expand Down
3 changes: 2 additions & 1 deletion packages/airnode-deployer/test/fixtures/config.valid.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
{
"maxConcurrency": 100,
"authorizers": {
"requesterEndpointAuthorizers": []
"requesterEndpointAuthorizers": [],
"crossChainRequesterAuthorizers": []
},
"authorizations": {
"requesterEndpointAuthorizations": {}
Expand Down
2 changes: 2 additions & 0 deletions packages/airnode-examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ reserved parameters. The following list orders integrations alphabetically:
authenticated cryptocurrency price request.
- [coingecko](https://github.com/api3dao/airnode/blob/master/packages/airnode-examples/integrations/coingecko) -
unauthenticated cryptocurrency price request.
- [coingecko-cross-chain-authorizer](https://github.com/api3dao/airnode/blob/master/packages/airnode-examples/integrations/coingecko) -
demonstration of a cross-chain [authorizer](https://docs.api3.org/airnode/latest/concepts/authorizers.html).
- [coingecko-post-processing](https://github.com/api3dao/airnode/tree/master/packages/airnode-examples/integrations/coingecko-post-processing) -
demonstration of the [post-processing](https://docs.api3.org/ois/latest/processing.html) feature.
- [coingecko-pre-processing](https://github.com/api3dao/airnode/tree/master/packages/airnode-examples/integrations/coingecko-pre-processing) -
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "@api3/airnode-protocol/contracts/authorizers/interfaces/IAuthorizerV0.sol";

contract EverythingAuthorizer is IAuthorizerV0 {
function isAuthorizedV0(
bytes32,
address,
bytes32,
address,
address
) external pure override returns (bool) {
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "@api3/airnode-protocol/contracts/authorizers/interfaces/IAuthorizerV0.sol";

contract NothingAuthorizer is IAuthorizerV0 {
function isAuthorizedV0(
bytes32,
address,
bytes32,
address,
address
) external pure override returns (bool) {
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "@api3/airnode-protocol/contracts/rrp/requesters/RrpRequesterV0.sol";

// An example requester which expects the response from Airnode to be a single int256 value.
contract Requester is RrpRequesterV0 {
mapping(bytes32 => bool) public incomingFulfillments;
mapping(bytes32 => int256) public fulfilledData;

constructor(address airnodeRrp) RrpRequesterV0(airnodeRrp) {}

function makeRequest(
address airnode,
bytes32 endpointId,
address sponsor,
address sponsorWallet,
bytes calldata parameters
) external {
bytes32 requestId = airnodeRrp.makeFullRequest(
airnode,
endpointId,
sponsor,
sponsorWallet,
address(this),
this.fulfill.selector,
parameters
);
incomingFulfillments[requestId] = true;
}

function fulfill(bytes32 requestId, bytes calldata data)
external
onlyAirnodeRrp
{
require(incomingFulfillments[requestId], "No such request made");
delete incomingFulfillments[requestId];
int256 decodedData = abi.decode(data, (int256));
fulfilledData[requestId] = decodedData;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
{
"maxConcurrency": 100,
"authorizers": {
"requesterEndpointAuthorizers": []
"requesterEndpointAuthorizers": [],
"crossChainRequesterAuthorizers": []
},
"authorizations": {
"requesterEndpointAuthorizations": {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const createConfig = async (generateExampleFile: boolean): Promise<Config> => ({
maxConcurrency: 100,
authorizers: {
requesterEndpointAuthorizers: [],
crossChainRequesterAuthorizers: [],
},
authorizations: {
requesterEndpointAuthorizations: {},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Coingecko Cross-chain Authorizer Example Integration

The basic coingecko integration has been modified to demonstrate a cross-chain authorizer. There are two authorizer
contracts: one, `NothingAuthorizer`, does not authorize any requests and the other, `EverythingAuthorizer`, authorizes
all requests. The `NothingAuthorizer` contract will be deployed to the first chain, which is the chain specified in the
`chains` array of `config.json` and the same as that on which Airnode will listen for and respond to requests. The
`EverythingAuthorizer` contract will be deployed to the second (cross) chain. With this arrangement, requests will be
authorized by the cross-chain authorizer and not by the same-chain authorizer. In a real use-case, the cross-chain
and/or same chain authorizer contracts would include logic for authorizing requests based on the requester, sponsor,
endpoint, etc.

To run this integration, all of the steps of the `airnode-examples` root-level README need to be followed in order, but
with one addition: the below command must be run prior to deploying the Airnode / running the Airnode container.

```sh
# Run from the <airnode/packages/airnode-examples> directory
yarn ts-node integrations/coingecko-cross-chain-authorizer/deploy-authorizers-and-update-config
```

This script will deploy the contracts described above to their respective chains and update placeholder addresses within
`config.json` with the actual addresses of the deployed contracts.
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
{
"chains": [
{
"maxConcurrency": 100,
"authorizers": {
"requesterEndpointAuthorizers": ["0xE2E0000000000000000000000000000000000000"],
"crossChainRequesterAuthorizers": [
{
"requesterEndpointAuthorizers": ["0xE2E1111111111111111111111111111111111111"],
"chainType": "evm",
"chainId": "31337",
"contracts": {
"AirnodeRrp": "0x5FbDB2315678afecb367f032d93F642f64180aa3"
},
"chainProvider": {
"url": "${PROVIDER_URL}"
}
}
]
},
"authorizations": {
"requesterEndpointAuthorizations": {}
},
"contracts": {
"AirnodeRrp": "0x5FbDB2315678afecb367f032d93F642f64180aa3"
},
"id": "31337",
"providers": {
"exampleProvider": {
"url": "${PROVIDER_URL}"
}
},
"type": "evm",
"options": {
"fulfillmentGasLimit": 500000,
"gasPriceOracle": [
{
"gasPriceStrategy": "latestBlockPercentileGasPrice",
"percentile": 60,
"minTransactionCount": 20,
"pastToCompareInBlocks": 20,
"maxDeviationMultiplier": 2
},
{
"gasPriceStrategy": "providerRecommendedGasPrice",
"recommendedGasPriceMultiplier": 1.2
},
{
"gasPriceStrategy": "constantGasPrice",
"gasPrice": {
"value": 10,
"unit": "gwei"
}
}
]
}
}
],
"nodeSettings": {
"cloudProvider": {
"type": "local"
},
"airnodeWalletMnemonic": "${AIRNODE_WALLET_MNEMONIC}",
"heartbeat": {
"enabled": false
},
"httpGateway": {
"enabled": false
},
"httpSignedDataGateway": {
"enabled": false
},
"logFormat": "plain",
"logLevel": "INFO",
"nodeVersion": "0.8.0",
"stage": "dev"
},
"triggers": {
"rrp": [
{
"endpointId": "0xfb87102cdabadf905321521ba0b3cbf74ad09c5d400ac2eccdbef8d6143e78c4",
"oisTitle": "CoinGecko basic request",
"endpointName": "coinMarketData",
"cacheResponses": false
}
],
"http": [],
"httpSignedData": []
},
"templates": [],
"ois": [
{
"oisFormat": "1.2.0",
"title": "CoinGecko basic request",
"version": "1.0.0",
"apiSpecifications": {
"servers": [
{
"url": "https://api.coingecko.com/api/v3"
}
],
"paths": {
"/coins/{id}": {
"get": {
"parameters": [
{
"in": "path",
"name": "id"
},
{
"in": "query",
"name": "localization"
},
{
"in": "query",
"name": "tickers"
},
{
"in": "query",
"name": "market_data"
},
{
"in": "query",
"name": "community_data"
},
{
"in": "query",
"name": "developer_data"
},
{
"in": "query",
"name": "sparkline"
}
]
}
}
},
"components": {
"securitySchemes": {}
},
"security": {}
},
"endpoints": [
{
"name": "coinMarketData",
"operation": {
"method": "get",
"path": "/coins/{id}"
},
"fixedOperationParameters": [
{
"operationParameter": {
"in": "query",
"name": "localization"
},
"value": "false"
},
{
"operationParameter": {
"in": "query",
"name": "tickers"
},
"value": "false"
},
{
"operationParameter": {
"in": "query",
"name": "market_data"
},
"value": "true"
},
{
"operationParameter": {
"in": "query",
"name": "community_data"
},
"value": "false"
},
{
"operationParameter": {
"in": "query",
"name": "developer_data"
},
"value": "false"
},
{
"operationParameter": {
"in": "query",
"name": "sparkline"
},
"value": "false"
}
],
"reservedParameters": [
{
"name": "_type",
"fixed": "int256"
},
{
"name": "_path",
"fixed": "market_data.current_price.usd"
},
{
"name": "_times",
"fixed": "1000000"
}
],
"parameters": [
{
"name": "coinId",
"operationParameter": {
"in": "path",
"name": "id"
}
}
]
}
]
}
],
"apiCredentials": []
}
Loading