Skip to content
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
67 changes: 8 additions & 59 deletions docs/fdc/reference/IAddressValidity.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ sidebar_position: 6
description: Assert whether a string represents a valid address.
---

import CodeBlock from "@theme/CodeBlock";
import AddressVerifier from "!!raw-loader!/examples/developer-hub-solidity/AddressVerifier.sol";
import Remix from "@site/src/components/remix";

Assert whether a string represents a valid address on an external blockchain.

Sourced from `IAddressValidity.sol` on [GitHub](https://github.com/flare-foundation/flare-smart-contracts-v2/blob/main/contracts/userInterfaces/fdc/IAddressValidity.sol).
Expand Down Expand Up @@ -142,62 +146,7 @@ struct ResponseBody {

## Usage Example

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@flare-foundation/flare-smart-contracts-v2/contracts/userInterfaces/IFdcHub.sol";
import "@flare-foundation/flare-smart-contracts-v2/contracts/userInterfaces/IFdcVerification.sol";
import "@flare-foundation/flare-smart-contracts-v2/contracts/userInterfaces/fdc/IAddressValidity.sol";

contract AddressVerifier {
IFdcHub private fdcHub;
IFdcVerification private fdcVerification;

bytes32 private constant ATTESTATION_TYPE_ADDRESS_VALIDITY = 0x0500000000000000000000000000000000000000000000000000000000000000;
bytes32 private constant SOURCE_ID_BTC = 0x4254430000000000000000000000000000000000000000000000000000000000;

constructor(address _fdcHubAddress, address _fdcVerificationAddress) {
fdcHub = IFdcHub(_fdcHubAddress);
fdcVerification = IFdcVerification(_fdcVerificationAddress);
}

// Request address validation
function requestAddressValidation(string calldata _address) external payable {
// Create request body
IAddressValidity.RequestBody memory requestBody = IAddressValidity.RequestBody({
addressStr: _address
});

// Encode the full request
bytes memory encodedRequest = abi.encode(
ATTESTATION_TYPE_ADDRESS_VALIDITY,
SOURCE_ID_BTC,
bytes32(0), // messageIntegrityCode (would need to be calculated properly)
requestBody
);

// Submit the request with payment
fdcHub.requestAttestation{value: msg.value}(encodedRequest);
}

// Verify a provided proof
function verifyAddressProof(IAddressValidity.Proof calldata _proof) external view returns (
bool isValid,
string memory standardAddress,
bytes32 standardAddressHash
) {
// Verify the proof using FdcVerification
bool proofVerified = fdcVerification.verifyAddressValidity(_proof);

if (proofVerified) {
// Extract data from the verified proof
isValid = _proof.data.responseBody.isValid;
standardAddress = _proof.data.responseBody.standardAddress;
standardAddressHash = _proof.data.responseBody.standardAddressHash;
}

return (isValid, standardAddress, standardAddressHash);
}
}
```
<CodeBlock language="solidity" title="AddressVerifier.sol">
{AddressVerifier}
</CodeBlock>
<Remix fileName="AddressVerifier.sol">Open example in Remix</Remix>
80 changes: 8 additions & 72 deletions docs/fdc/reference/IBalanceDecreasingTransaction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ sidebar_position: 7
description: Detect a transaction that decreases an address balance.
---

import CodeBlock from "@theme/CodeBlock";
import LockMonitor from "!!raw-loader!/examples/developer-hub-solidity/LockMonitor.sol";
import Remix from "@site/src/components/remix";

An interface to detect transactions that decrease the balance of a specific address or are signed by that address on external blockchains.

Sourced from `IBalanceDecreasingTransaction.sol` on [GitHub](https://github.com/flare-foundation/flare-smart-contracts-v2/blob/main/contracts/userInterfaces/fdc/IBalanceDecreasingTransaction.sol).
Expand Down Expand Up @@ -239,75 +243,7 @@ Response body containing details about the balance decreasing transaction.

## Usage Example

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@flare-foundation/flare-smart-contracts-v2/contracts/userInterfaces/IFdcHub.sol";
import "@flare-foundation/flare-smart-contracts-v2/contracts/userInterfaces/IFdcVerification.sol";
import "@flare-foundation/flare-smart-contracts-v2/contracts/userInterfaces/fdc/IBalanceDecreasingTransaction.sol";

contract LockMonitor {
IFdcHub private fdcHub;
IFdcVerification private fdcVerification;

bytes32 private constant ATTESTATION_TYPE_BALANCE_DECREASING = 0x0200000000000000000000000000000000000000000000000000000000000000;
bytes32 private constant SOURCE_ID_BTC = 0x4254430000000000000000000000000000000000000000000000000000000000;

mapping(bytes32 => bool) public lockedAddresses; // sourceAddressHash => isLocked

constructor(address _fdcHubAddress, address _fdcVerificationAddress) {
fdcHub = IFdcHub(_fdcHubAddress);
fdcVerification = IFdcVerification(_fdcVerificationAddress);
}

// Register an address as locked (should not spend funds)
function registerLockedAddress(bytes32 sourceAddressHash) external {
lockedAddresses[sourceAddressHash] = true;
}

// Request verification of a transaction that might violate lock agreement
function checkViolation(bytes32 transactionId, bytes32 sourceAddressIndicator) external payable {
// Create request body
IBalanceDecreasingTransaction.RequestBody memory requestBody = IBalanceDecreasingTransaction.RequestBody({
transactionId: transactionId,
sourceAddressIndicator: sourceAddressIndicator
});

// Encode the full request
bytes memory encodedRequest = abi.encode(
ATTESTATION_TYPE_BALANCE_DECREASING,
SOURCE_ID_BTC,
bytes32(0), // messageIntegrityCode (would need to be calculated properly)
requestBody
);

// Submit the request with payment
fdcHub.requestAttestation{value: msg.value}(encodedRequest);
}

// Verify a provided proof and take action if a locked address has spent funds
function verifyViolation(IBalanceDecreasingTransaction.Proof calldata _proof)
external
returns (bool isViolation)
{
// Verify the proof using FdcVerification
bool proofVerified = fdcVerification.verifyBalanceDecreasingTransaction(_proof);

if (proofVerified) {
// Extract the sourceAddressHash
bytes32 sourceAddressHash = _proof.data.responseBody.sourceAddressHash;
int256 spentAmount = _proof.data.responseBody.spentAmount;

// Check if this is a locked address and the amount spent is positive
if (lockedAddresses[sourceAddressHash] && spentAmount > 0) {
// Take action - e.g., liquidate collateral, notify stakeholders, etc.
lockedAddresses[sourceAddressHash] = false; // Remove from locked addresses
return true;
}
}

return false;
}
}
```
<CodeBlock language="solidity" title="LockMonitor.sol">
{LockMonitor}
</CodeBlock>
<Remix fileName="LockMonitor.sol">Open example in Remix</Remix>
81 changes: 8 additions & 73 deletions docs/fdc/reference/IConfirmedBlockHeightExists.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ sidebar_position: 8
description: Assert that a block number is confirmed.
---

import CodeBlock from "@theme/CodeBlock";
import BlockchainMonitor from "!!raw-loader!/examples/developer-hub-solidity/BlockchainMonitor.sol";
import Remix from "@site/src/components/remix";

An interface to verify that a specified block has been confirmed on an external blockchain and to calculate block production rates.

Sourced from `IConfirmedBlockHeightExists.sol` on [GitHub](https://github.com/flare-foundation/flare-smart-contracts-v2/blob/main/contracts/userInterfaces/fdc/IConfirmedBlockHeightExists.sol).
Expand Down Expand Up @@ -207,79 +211,10 @@ average_block_time = time_elapsed / blocks_produced

## Usage Example

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@flare-foundation/flare-smart-contracts-v2/contracts/userInterfaces/IFdcHub.sol";
import "@flare-foundation/flare-smart-contracts-v2/contracts/userInterfaces/IFdcVerification.sol";
import "@flare-foundation/flare-smart-contracts-v2/contracts/userInterfaces/fdc/IConfirmedBlockHeightExists.sol";

contract BlockchainMonitor {
IFdcHub private fdcHub;
IFdcVerification private fdcVerification;

bytes32 private constant ATTESTATION_TYPE_CONFIRMED_BLOCK = 0x0200000000000000000000000000000000000000000000000000000000000000;
bytes32 private constant SOURCE_ID_BTC = 0x4254430000000000000000000000000000000000000000000000000000000000;

constructor(address _fdcHubAddress, address _fdcVerificationAddress) {
fdcHub = IFdcHub(_fdcHubAddress);
fdcVerification = IFdcVerification(_fdcVerificationAddress);
}

// Request confirmation of a block
function requestBlockConfirmation(uint64 blockNumber, uint64 queryWindow) external payable {
// Create request body
IConfirmedBlockHeightExists.RequestBody memory requestBody = IConfirmedBlockHeightExists.RequestBody({
blockNumber: blockNumber,
queryWindow: queryWindow
});

// Encode the full request
bytes memory encodedRequest = abi.encode(
ATTESTATION_TYPE_CONFIRMED_BLOCK,
SOURCE_ID_BTC,
bytes32(0), // messageIntegrityCode (would need to be calculated properly)
requestBody
);

// Submit the request with payment
fdcHub.requestAttestation{value: msg.value}(encodedRequest);
}

// Verify a provided proof and calculate block rate
function verifyBlockAndCalculateRate(IConfirmedBlockHeightExists.Proof calldata _proof)
external view
returns (
bool blockConfirmed,
uint64 avgBlockTimeSeconds
)
{
// Verify the proof using FdcVerification
bool proofVerified = fdcVerification.verifyConfirmedBlockHeightExists(_proof);

if (proofVerified) {
// Extract data for calculation
uint64 blockNumber = _proof.data.requestBody.blockNumber;
uint64 blockTimestamp = _proof.data.responseBody.blockTimestamp;
uint64 lowestNumber = _proof.data.responseBody.lowestQueryWindowBlockNumber;
uint64 lowestTimestamp = _proof.data.responseBody.lowestQueryWindowBlockTimestamp;

// Calculate average block time
uint64 blocksProduced = blockNumber - lowestNumber;
uint64 timeElapsed = blockTimestamp - lowestTimestamp;

if (blocksProduced > 0) {
avgBlockTimeSeconds = timeElapsed / blocksProduced;
}

return (true, avgBlockTimeSeconds);
}

return (false, 0);
}
}
```
<CodeBlock language="solidity" title="BlockchainMonitor.sol">
{BlockchainMonitor}
</CodeBlock>
<Remix fileName="BlockchainMonitor.sol">Open example in Remix</Remix>

## Related Interfaces

Expand Down
104 changes: 8 additions & 96 deletions docs/fdc/reference/IEVMTransaction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ sidebar_position: 9
description: Relay a transaction from an EVM chain.
---

import CodeBlock from "@theme/CodeBlock";
import EVMTransactionVerifier from "!!raw-loader!/examples/developer-hub-solidity/EVMTransactionVerifier.sol";
import Remix from "@site/src/components/remix";

An interface to relay and verify transactions from EVM-compatible blockchains.

Sourced from `IEVMTransaction.sol` on [GitHub](https://github.com/flare-foundation/flare-smart-contracts-v2/blob/main/contracts/userInterfaces/fdc/IEVMTransaction.sol).
Expand Down Expand Up @@ -251,99 +255,7 @@ When working with events, it's important to remember:

## Usage Example

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@flare-foundation/flare-smart-contracts-v2/contracts/userInterfaces/IFdcHub.sol";
import "@flare-foundation/flare-smart-contracts-v2/contracts/userInterfaces/IFdcVerification.sol";
import "@flare-foundation/flare-smart-contracts-v2/contracts/userInterfaces/fdc/IEVMTransaction.sol";

contract EVMTransactionVerifier {
IFdcHub private fdcHub;
IFdcVerification private fdcVerification;

bytes32 private constant ATTESTATION_TYPE_EVM_TX = 0x0600000000000000000000000000000000000000000000000000000000000000;
bytes32 private constant SOURCE_ID_ETH = 0x4554480000000000000000000000000000000000000000000000000000000000;

// Event signatures we're interested in
bytes32 private constant EVENT_TRANSFER = 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;

constructor(address _fdcHubAddress, address _fdcVerificationAddress) {
fdcHub = IFdcHub(_fdcHubAddress);
fdcVerification = IFdcVerification(_fdcVerificationAddress);
}

// Request verification of an EVM transaction with specific events
function requestTransactionVerification(
bytes32 transactionHash,
uint16 requiredConfirmations,
bool includeInput,
uint32[] calldata eventIndices
) external payable {
// Create request body
IEVMTransaction.RequestBody memory requestBody = IEVMTransaction.RequestBody({
transactionHash: transactionHash,
requiredConfirmations: requiredConfirmations,
provideInput: includeInput,
listEvents: eventIndices.length > 0,
logIndices: eventIndices
});

// Encode the full request
bytes memory encodedRequest = abi.encode(
ATTESTATION_TYPE_EVM_TX,
SOURCE_ID_ETH,
bytes32(0), // messageIntegrityCode (would need to be calculated properly)
requestBody
);

// Submit the request with payment
fdcHub.requestAttestation{value: msg.value}(encodedRequest);
}

// Verify a provided proof and extract ERC-20 transfer information
function verifyERC20Transfer(IEVMTransaction.Proof calldata _proof)
external view
returns (
bool success,
address tokenContract,
address from,
address to,
uint256 amount
)
{
// Verify the proof using FdcVerification
bool proofVerified = fdcVerification.verifyEVMTransaction(_proof);

if (proofVerified && _proof.data.responseBody.status == 1) {
// Look for Transfer events in the transaction
IEVMTransaction.Event[] memory events = _proof.data.responseBody.events;

for (uint i = 0; i < events.length; i++) {
IEVMTransaction.Event memory evt = events[i];

// Check if this is a Transfer event (topic[0] is the event signature)
if (evt.topics.length >= 3 && evt.topics[0] == EVENT_TRANSFER) {
tokenContract = evt.emitterAddress;

// ERC-20 Transfer(address indexed from, address indexed to, uint256 amount)
// topics[1] is the first indexed parameter (from address)
// topics[2] is the second indexed parameter (to address)
// The addresses are padded to 32 bytes, so we need to extract them
from = address(uint160(uint256(evt.topics[1])));
to = address(uint160(uint256(evt.topics[2])));

// The amount is in the data field for non-indexed parameters
// It's a single uint256 value (32 bytes)
amount = abi.decode(evt.data, (uint256));

return (true, tokenContract, from, to, amount);
}
}
}

return (false, address(0), address(0), address(0), 0);
}
}
```
<CodeBlock language="solidity" title="EVMTransactionVerifier.sol">
{EVMTransactionVerifier.toString()}
</CodeBlock>
<Remix fileName="EVMTransactionVerifier.sol">Open example in Remix</Remix>
Loading