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

feat: add greenfield demo that contract delegate eoa upload file (#158) #160

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
58 changes: 58 additions & 0 deletions contracts/example/GreenfieldDemo.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "../interface/IBucketHub.sol";
import "../interface/ITokenHub.sol";
import "../interface/ICrossChain.sol";
import "../interface/IPermissionHub.sol";
import "../interface/IGreenfieldExecutor.sol";

contract GreenfieldDemo {
// testnet
address public constant TOKEN_HUB = 0xED8e5C546F84442219A5a987EE1D820698528E04;
address public constant CROSS_CHAIN = 0xa5B2c9194131A4E0BFaCbF9E5D6722c873159cb7;
address public constant BUCKET_HUB = 0x5BB17A87D03620b313C39C24029C94cB5714814A;
address public constant PERMISSION_HUB = 0x25E1eeDb5CaBf288210B132321FBB2d90b4174ad;
address public constant SP_ADDRESS_TESTNET = 0x5FFf5A6c94b182fB965B40C7B9F30199b969eD2f;
address public constant GREENFIELD_EXECUTOR = 0x3E3180883308e8B4946C9a485F8d91F8b15dC48e;

function createBucket(
string memory bucketName,
uint256 transferOutAmount,
bytes memory _executorData
) external payable {
(uint256 relayFee, uint256 ackRelayFee) = ICrossChain(CROSS_CHAIN).getRelayFees();
require(msg.value == transferOutAmount + relayFee * 3 + ackRelayFee * 2, "msg.value not enough");

// 1. transferOut to address(this) on greenfield
ITokenHub(TOKEN_HUB).transferOut{ value: transferOutAmount + relayFee + ackRelayFee }(
address(this),
transferOutAmount
);

// 2. set bucket flow rate limit
uint8[] memory _msgTypes = new uint8[](1);
_msgTypes[0] = 9; // * 9: SetBucketFlowRateLimit
bytes[] memory _msgBytes = new bytes[](1);
_msgBytes[0] = _executorData;
IGreenfieldExecutor(GREENFIELD_EXECUTOR).execute{ value: relayFee }(_msgTypes, _msgBytes);

// 3. create bucket, owner = address(this)
BucketStorage.CreateBucketSynPackage memory createPackage = BucketStorage.CreateBucketSynPackage({
creator: address(this),
name: bucketName,
visibility: BucketStorage.BucketVisibilityType.Private,
paymentAddress: address(this),
primarySpAddress: SP_ADDRESS_TESTNET,
primarySpApprovalExpiredHeight: 0,
globalVirtualGroupFamilyId: 1,
primarySpSignature: new bytes(0),
chargedReadQuota: 10485760000,
extraData: new bytes(0)
});
IBucketHub(BUCKET_HUB).createBucket{ value: relayFee + ackRelayFee }(createPackage);
}

function createPolicy(bytes memory createPolicyData) external payable {
IPermissionHub(PERMISSION_HUB).createPolicy{ value: msg.value }(createPolicyData);
}
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
"@openzeppelin/contracts-upgradeable": "4.9.3"
},
"devDependencies": {
"@bnb-chain/bsc-cross-greenfield-sdk": "^0.0.2",
"@bnb-chain/greenfield-js-sdk": "^2.0.1",
"@ethersproject/abi": "^5.4.7",
"@ethersproject/providers": "^5.4.7",
"@nomicfoundation/hardhat-chai-matchers": "^1.0.6",
Expand Down
1 change: 0 additions & 1 deletion scripts/10-upgrade-erc2771forwarder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ const main = async () => {
const implGreenfieldExecutor = await deployContract('GreenfieldExecutor');
log('new implGreenfieldExecutor deployed', implGreenfieldExecutor.address);


const addGroupHub = await deployContract('AdditionalGroupHub');
log('new addGroupHub deployed', addGroupHub.address);

Expand Down
105 changes: 105 additions & 0 deletions scripts/11-demo-contract-approve-eoa-upload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { GreenfieldDemo, ICrossChain } from '../typechain-types';
import { sleep, toHuman } from './helper';
import { deployContract, waitTx } from '../test/helper';
import { ExecutorMsg } from '@bnb-chain/bsc-cross-greenfield-sdk';
import { Policy } from '@bnb-chain/greenfield-cosmos-types/greenfield/permission/types';
import { ResourceType } from '@bnb-chain/greenfield-cosmos-types/greenfield/resource/types';
import {
ActionType,
Effect,
PrincipalType,
} from '@bnb-chain/greenfield-cosmos-types/greenfield/permission/common';
import { Client } from '@bnb-chain/greenfield-js-sdk';
import { ethers } from 'hardhat';

const log = console.log;

const main = async () => {
const GRPC_URL = 'https://gnfd-testnet-fullnode-tendermint-us.bnbchain.org';
const GREEN_CHAIN_ID = 'greenfield_5600-1';
const client = Client.create(GRPC_URL, GREEN_CHAIN_ID);

const [operator] = await ethers.getSigners();
log('operator', operator.address);
const balance = await ethers.provider.getBalance(operator.address);
log('operator.address: ', operator.address, toHuman(balance));

// 1. deploy demo contract
const demo = (await deployContract(operator, 'GreenfieldDemo')) as GreenfieldDemo;
log('demo contract deployed!', demo.address);
log(`https://testnet.bscscan.com/address/${demo.address}`);
const CROSS_CHAIN = await demo.CROSS_CHAIN();
const crossChain = (await ethers.getContractAt('ICrossChain', CROSS_CHAIN)) as ICrossChain;
const [relayFee, ackRelayFee] = await crossChain.callStatic.getRelayFees();

// 2. createBucket
const bucketName = 'test-' + demo.address.substring(2, 6).toLowerCase();
// - transferOutAmt: 0.1 BNB to demo contract on Greenfield
// - set bucket flow rate limit to this bucket
// - create bucket: 'test-approve-eoa-upload', its owner is demo contract
const dataSetBucketFlowRateLimit = ExecutorMsg.getSetBucketFlowRateLimitParams({
bucketName,
bucketOwner: demo.address,
operator: demo.address,
paymentAddress: demo.address,
flowRateLimit: '1000000000000000000',
});
const executorData = dataSetBucketFlowRateLimit[1];
const transferOutAmt = ethers.utils.parseEther('0.1');
const value = transferOutAmt.add(relayFee.mul(3).add(ackRelayFee.mul(2)));

log('- transfer out to demo contract on greenfield', toHuman(transferOutAmt));
log('- create bucket', bucketName);
log('send crosschain tx!');
const receipt = await waitTx(
demo.createBucket(bucketName, transferOutAmt, executorData, { value })
);
log(`https://testnet.bscscan.com/tx/${receipt.transactionHash}`);

// 3. get bucket id by name
log('waiting for bucket created..., about 1 minute');
await sleep(60); // waiting bucket created

const bucketInfo = await client.bucket.getBucketMeta({ bucketName });
const bucketId = bucketInfo.body!.GfSpGetBucketMetaResponse.Bucket.BucketInfo.Id;
log('bucket created, bucket id', bucketId);
const hexBucketId = `0x000000000000000000000000000000000000000000000000000000000000${BigInt(
bucketId
).toString(16)}`;
log(`https://testnet.greenfieldscan.com/bucket/${hexBucketId}`);

const uploaderEoaAccount = operator.address; // TODO set your eoa account to upload files
log('try to set uploader(eoa account) is', uploaderEoaAccount);

const policyDataToAllowUserOperateBucket = Policy.encode({
id: '0',
resourceId: bucketId, // bucket id
resourceType: ResourceType.RESOURCE_TYPE_BUCKET,
statements: [
{
effect: Effect.EFFECT_ALLOW,
actions: [ActionType.ACTION_CREATE_OBJECT], // allow upload file to the bucket
resources: [],
},
],
principal: {
type: PrincipalType.PRINCIPAL_TYPE_GNFD_ACCOUNT,
value: uploaderEoaAccount,
},
}).finish();

await waitTx(
demo.createPolicy(policyDataToAllowUserOperateBucket, { value: relayFee.add(ackRelayFee) })
);

log(
`policy set success, ${uploaderEoaAccount} could upload file to the bucket ${bucketName} (id: ${bucketId}) now on Greenfield`
);
};

main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
Loading
Loading