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
25 changes: 11 additions & 14 deletions contracts/chain-adapters/Solana_Adapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { IMessageTransmitter, ITokenMessenger } from "../external/interfaces/CCT
import { SpokePoolInterface } from "../interfaces/SpokePoolInterface.sol";
import { AdapterInterface } from "./interfaces/AdapterInterface.sol";
import { CircleCCTPAdapter, CircleDomainIds } from "../libraries/CircleCCTPAdapter.sol";
import { Bytes32ToAddress } from "../libraries/AddressConverters.sol";

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

Expand All @@ -19,6 +20,14 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

// solhint-disable-next-line contract-name-camelcase
contract Solana_Adapter is AdapterInterface, CircleCCTPAdapter {
/**
* @notice We use Bytes32ToAddress library to map a Solana address to an Ethereum address representation.
* @dev The Ethereum address is derived from the Solana address by truncating it to its lowest 20 bytes. This same
* conversion must be done by the HubPool owner when adding Solana spoke pool and setting the corresponding pool
* rebalance and deposit routes.
*/
using Bytes32ToAddress for bytes32;

/**
* @notice The official Circle CCTP MessageTransmitter contract endpoint.
* @dev Posted officially here: https://developers.circle.com/stablecoins/docs/evm-smart-contracts
Expand Down Expand Up @@ -84,10 +93,10 @@ contract Solana_Adapter is AdapterInterface, CircleCCTPAdapter {
cctpMessageTransmitter = _cctpMessageTransmitter;

SOLANA_SPOKE_POOL_BYTES32 = solanaSpokePool;
SOLANA_SPOKE_POOL_ADDRESS = _trimSolanaAddress(solanaSpokePool);
SOLANA_SPOKE_POOL_ADDRESS = solanaSpokePool.toAddressUnchecked();

SOLANA_USDC_BYTES32 = solanaUsdc;
SOLANA_USDC_ADDRESS = _trimSolanaAddress(solanaUsdc);
SOLANA_USDC_ADDRESS = solanaUsdc.toAddressUnchecked();

SOLANA_SPOKE_POOL_USDC_VAULT = solanaSpokePoolUsdcVault;
}
Expand Down Expand Up @@ -151,18 +160,6 @@ contract Solana_Adapter is AdapterInterface, CircleCCTPAdapter {
emit TokensRelayed(l1Token, l2Token, amount, to);
}

/**
* @notice Helper to map a Solana address to an Ethereum address representation.
* @dev The Ethereum address is derived from the Solana address by truncating it to its lowest 20 bytes. This same
* conversion must be done by the HubPool owner when adding Solana spoke pool and setting the corresponding pool
* rebalance and deposit routes.
* @param solanaAddress Solana address (Base58 decoded to bytes32) to map to its Ethereum address representation.
* @return Ethereum address representation of the Solana address.
*/
function _trimSolanaAddress(bytes32 solanaAddress) internal pure returns (address) {
return address(uint160(uint256(solanaAddress)));
}

/**
* @notice Translates a message to enable/disable a route on Solana spoke pool.
* @param message Message to translate, expecting setEnableRoute(address,uint256,bool).
Expand Down
13 changes: 12 additions & 1 deletion contracts/libraries/AddressConverters.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,19 @@
pragma solidity ^0.8.0;

library Bytes32ToAddress {
/**************************************
* ERRORS *
**************************************/
error InvalidBytes32();

function toAddress(bytes32 _bytes32) internal pure returns (address) {
require(uint256(_bytes32) >> 192 == 0, "Invalid bytes32: highest 12 bytes must be 0");
if (uint256(_bytes32) >> 192 != 0) {
revert InvalidBytes32();
}
return address(uint160(uint256(_bytes32)));
}

function toAddressUnchecked(bytes32 _bytes32) internal pure returns (address) {
return address(uint160(uint256(_bytes32)));
}
}
Expand Down
2 changes: 1 addition & 1 deletion test/evm/hardhat/chain-adapters/Solana_Adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ describe("Solana Chain Adapter", function () {
const functionCallData = mockSpoke.interface.encodeFunctionData("setCrossDomainAdmin", [newAdmin]);
expect(await hubPool.relaySpokePoolAdminFunction(solanaChainId, functionCallData))
.to.emit(solanaAdapter.attach(hubPool.address), "MessageRelayed")
.withArgs(solanaSpokePoolAddress, functionCallData);
.withArgs(solanaSpokePoolAddress.toLowerCase(), functionCallData);
expect(cctpMessageTransmitter.sendMessage).to.have.been.calledWith(
solanaDomainId,
solanaSpokePoolBytes32,
Expand Down
Loading