Step 2 - Start Solidity Contract
2.1 Solidity Contract with Interface
Solidity interfaces are useful for calling external contracts that might have different compiler versions.
For example: new protocols might use more recent Solidity compiler versions for contracts while wanting to use WETH9.sol. This can be done using an ERC-20 interface such as IERC20.sol to avoid Solidity compiler errors from using incompatible Solidity compiler versions.
In this context, a Solidity interface is used to call an external Rust contract based on its method name and types.
contracts/FluentSdkRustTypesTest.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
interface IFluentRust {
// Make sure type interfaces are defined here or else there will be a compiler error.
function rustString() external view returns (string memory);
function rustUint256() external view returns (uint256);
// function rustInt256() external view returns (int256);
function rustAddress() external view returns (address);
function rustBytes() external view returns (bytes memory);
function rustBytes32() external view returns (bytes32);
function rustBool() external view returns (bool);
}
contract FluentSdkRustTypesTest {
IFluentRust public fluentRust;
constructor(address FluentRustAddress) {
fluentRust = IFluentRust(FluentRustAddress);
}
function getRustString() external view returns (string memory) {
string memory rustString = fluentRust.rustString();
return string(abi.encodePacked(rustString, " World"));
}
function getRustUint256() external view returns (uint256) {
uint256 rustUint256 = fluentRust.rustUint256();
return rustUint256;
}
// function getRustInt256() external view returns (int256) {
// int256 rustInt256 = fluentRust.rustInt256();
// return rustInt256;
// }
function getRustAddress() external view returns (address) {
address rustAddress = fluentRust.rustAddress();
return rustAddress;
}
function getRustBytes() external view returns (bytes memory) {
bytes memory rustBytes = fluentRust.rustBytes();
return rustBytes;
}
function getRustBytes32() external view returns (bytes32) {
bytes32 rustBytes32 = fluentRust.rustBytes32();
return rustBytes32;
}
function getRustBool() external view returns (bool) {
bool rustBool = fluentRust.rustBool();
return rustBool;
}
}
Detailed Code Explanation
Import Statement: Imports the IFluentGreeting
interface defined earlier.
Contract Definition: Defines a contract GreetingWithWorld
.
State Variable: Declares a state variable fluentGreetingContract
of type IFluentGreeting
. This variable will hold the address of the deployed Rust smart contract.
Constructor:
-
Takes an address
_fluentGreetingContractAddress
as a parameter. -
Initializes the
fluentGreetingContract
with the provided address. -
Function
getGreeting
:- Calls the
greeting
function of thefluentGreetingContract
to get the greeting message from the Rust contract. - Concatenates the greeting message with ", World" using
abi.encodePacked
and returns the resulting string.
- Calls the
Interaction with Rust Code:
- The
GreetingWithWorld
contract interacts with the Rust smart contract by calling thegreeting
function via theIFluentGreeting
interface. - When
getGreeting
is called, it fetches the greeting message ("Hello") from the Rust contract, concatenates it with ", World", and returns the complete greeting ("Hello, World").
How Solidity and Rust Interact:
- Rust Smart Contract Deployment: The Rust smart contract is compiled to Wasm and deployed to the blockchain. It contains a function that returns the greeting "Hello".
- Solidity Interface (
IFluentGreeting
): The Solidity interface declares agreeting
function that matches the function in the Rust contract. - Solidity Implementation (
GreetingWithWorld
):- The
GreetingWithWorld
contract uses theIFluentGreeting
interface to interact with the Rust contract. - It initializes with the address of the deployed Rust contract.
- It calls the
greeting
function of the Rust contract to fetch the greeting message. - It concatenates the Rust greeting with ", World" and returns the result.
- The