Skip to content

Commit e7bdde9

Browse files
nonergodickcsongor
andauthored
Restructure and update repo (#31)
* restructure repo in line with new, expanded purpose * fix typo * bump solc version to 8.19 (last version before shanghai) * move remappings into foundry.toml * fix foundry.toml syntax mishap * Update README.md Co-authored-by: Csongor Kiss <[email protected]> * Update README.md Co-authored-by: Csongor Kiss <[email protected]> * updated README * fix failing tests * fix vm.assume rejected too many inputs error in query tests --------- Co-authored-by: Csongor Kiss <[email protected]>
1 parent b9e129e commit e7bdde9

33 files changed

+292
-261
lines changed

README.md

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,55 @@
11
# Wormhole Solidity SDK
22

3-
The purpose of this SDK is to provide helpers to take your existing single-chain solidity application cross-chain using Wormhole's automatic relayers
3+
The purpose of this SDK is to make on-chain integrations with Wormhole on EVM compatible chains as smooth as possible by providing all necessary Solidity interfaces along with useful libraries and tools for testing.
44

5-
### Installation
5+
For off-chain code, please refer to the [TypeScript SDK](https://github.com/wormhole-foundation/wormhole-sdk-ts) and in particular the [EVM platform implementation](https://github.com/wormhole-foundation/wormhole-sdk-ts/tree/main/platforms/evm).
6+
7+
This SDK was originally created for integrations with the WormholeRelayer and then expanded to cover all integration.
8+
9+
## Installation
610

711
**Foundry and Forge**
812

913
```bash
1014
forge install wormhole-foundation/wormhole-solidity-sdk
1115
```
1216

13-
### Example Usage + Introduction to Automatic Relayers
17+
**Solc Version**
18+
19+
Currently the SDK uses solc version 0.8.19 to avoid issues with PUSH0 which was introduced in 0.8.20 but which is not supported on many EVM chains.
20+
21+
## WormholeRelayer
22+
23+
### Introduction
24+
25+
The WormholeRelayer (also sometimes referred to as the automatic or generic relayer) allows integrators to leverage external parties known as delivery providers, to relay messages emitted on a given source chain to the intended target chain.
26+
27+
This frees integrators, who are building a cross-chain app, from the cumbersome and painful task of having to run relaying infrastructure themselves (and thus e.g. dealing with the headache of having to acquire gas tokens for the target chain).
28+
29+
Messages include, but aren't limited to: Wormhole attestations (VAAs), Circle attestations (CCTP)
30+
31+
Delivery providers provide a quote for the cost of a delivery on the source chain and also take payment there. This means the process is not fully trustless (delivery providers can take payment and then fail to perform the delivery), however the state of the respective chains always makes it clear whether a delivery provider has done their duty for a given delivery and delivery providers can't maliciously manipulate the content of a delivery.
32+
33+
### Example Usage
1434

1535
[HelloWormhole - Simple cross-chain message sending application](https://github.com/wormhole-foundation/hello-wormhole)
1636

17-
[HelloToken - Simple cross-chain token sending application](https://github.com/wormhole-foundation/hello-tokens)
37+
[HelloToken - Simple cross-chain token sending application](https://github.com/wormhole-foundation/hello-token)
1838

1939
[HelloUSDC - Simple cross-chain USDC sending application using CCTP](https://github.com/wormhole-foundation/hello-usdc)
2040

2141
### SDK Summary
2242

2343
- Includes interfaces to interact with contracts in the Wormhole ecosystem ([src/interfaces](https://github.com/wormhole-foundation/wormhole-solidity-sdk/tree/main/src/interfaces))
2444
- Includes the base class ‘Base’ with helpers for common actions that will typically need to be done within ‘receiveWormholeMessages’:
25-
- [`onlyWormholeRelayer()`](https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/main/src/Base.sol#L24): Checking that msg.sender is the wormhole relayer contract
26-
Sometimes, Cross-chain applications may be set up such that there is one ‘spoke’ contract on every chain, which sends messages to the ‘hub’ contract. If so, we’d ideally only want to allow messages to be sent from these spoke contracts. Included are helpers for this:
27-
28-
- [`setRegisteredSender(uint16 sourceChain, bytes32 sourceAddress)`](https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/main/src/Base.sol#L47): Setting the specified sender for ‘sourceChain’ to be ‘sourceAddress’
29-
- [`isRegisteredSender(uint16 sourceChain, bytes32 sourceAddress)`](https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/main/src/Base.sol#L35): Checking that the sender who requested the delivery is the registered address for that chain
45+
- [`onlyWormholeRelayer()`](https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/main/src/WormholeRelayer/Base.sol#L24): Checking that msg.sender is the wormhole relayer contract
46+
Sometimes, cross-chain applications may be set up such that there is one ‘spoke’ contract on every chain, which sends messages to the ‘hub’ contract. If so, we’d ideally only want to allow messages to be sent from these spoke contracts. Included are helpers for this:
3047

31-
Look at test/Counter.t.sol for an example usage of Base
48+
- [`setRegisteredSender(uint16 sourceChain, bytes32 sourceAddress)`](https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/main/src/WormholeRelayer/Base.sol#L45): Setting the specified sender for ‘sourceChain’ to be ‘sourceAddress’
49+
- [`isRegisteredSender(uint16 sourceChain, bytes32 sourceAddress)`](https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/main/src/WormholeRelayer/Base.sol#L30): Checking that the sender who requested the delivery is the registered address for that chain
3250

33-
- Included are also the ‘[TokenSender](https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/main/src/TokenBase#L36)’ and ‘[TokenReceiver](https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/main/src/TokenBase.sol#L126)’ base classes with helpers for smart contracts that wish to send and receive tokens using Wormhole’s TokenBridge. See ‘[HelloToken](https://github.com/wormhole-foundation/hello-token)’ for example usage.
34-
- Included are also the ‘[CCTPSender](https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/main/src/CCTPBase#L70)’ and ‘[CCTPReceiver](https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/main/src/CCTPBase.sol#L134)’ base classes with helpers for smart contracts that wish to send and receive both tokens using Wormhole’s TokenBridge as well as USDC using CCTP. See ‘[HelloUSDC](https://github.com/wormhole-foundation/hello-usdc)’ for example usage.
51+
- Included are also the ‘[TokenSender](https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/main/src/WormholeRelayer/TokenBase#L36)’ and ‘[TokenReceiver](https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/main/src/WormholeRelayer/TokenBase.sol#L126)’ base classes with helpers for smart contracts that wish to send and receive tokens using Wormhole’s TokenBridge. See ‘[HelloToken](https://github.com/wormhole-foundation/hello-token)’ for example usage.
52+
- Included are also the ‘[CCTPSender](https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/main/src/WormholeRelayer/CCTPBase#L59)’ and ‘[CCTPReceiver](https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/main/src/WormholeRelayer/CCTPBase.sol#L177)’ base classes with helpers for smart contracts that wish to send and receive both tokens using Wormhole’s TokenBridge as well as USDC using CCTP. See ‘[HelloUSDC](https://github.com/wormhole-foundation/hello-usdc)’ for example usage.
3553
- Included are helpers that help set up a local forge testing environment. See ‘[HelloWormhole](https://github.com/wormhole-foundation/hello-wormhole)’ for example usage.
3654

3755
**Note: This code is meant to be used as starter / reference code. Feel free to modify for use in your contracts, and also make sure to audit any code used from here as part of your contracts before deploying to mainnet.**

foundry.toml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
[profile.default]
2-
solc_version = "0.8.13"
2+
solc_version = "0.8.19"
33
src = "src"
44
out = "out"
55
libs = ["lib"]
66
via_ir = true
77

8-
# See more config options https://github.com/foundry-rs/foundry/tree/master/config
8+
remappings = [
9+
"ds-test/=lib/forge-std/lib/ds-test/src/",
10+
"forge-std/=lib/forge-std/src/",
11+
"wormhole-sdk/=src/",
12+
]
13+
14+
# See more config options https://github.com/foundry-rs/foundry/tree/master/config

remappings.txt

Lines changed: 0 additions & 2 deletions
This file was deleted.

src/Chains.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: Apache 2
2-
pragma solidity ^0.8.13;
2+
pragma solidity ^0.8.19;
33

44
// In the wormhole wire format, 0 indicates that a message is for any destination chain
55
uint16 constant CHAIN_ID_UNSET = 0;

src/Utils.sol

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11

22
// SPDX-License-Identifier: Apache 2
3-
pragma solidity ^0.8.13;
3+
pragma solidity ^0.8.19;
44

5-
import "./interfaces/IWormholeRelayer.sol";
5+
error NotAnEvmAddress(bytes32);
66

7-
function toWormholeFormat(address addr) pure returns (bytes32) {
8-
return bytes32(uint256(uint160(addr)));
7+
function toUniversalAddress(address addr) pure returns (bytes32 universalAddr) {
8+
universalAddr = bytes32(uint256(uint160(addr)));
99
}
1010

11-
function fromWormholeFormat(bytes32 whFormatAddress) pure returns (address) {
12-
if (uint256(whFormatAddress) >> 160 != 0) {
13-
revert NotAnEvmAddress(whFormatAddress);
11+
function fromUniversalAddress(bytes32 universalAddr) pure returns (address addr) {
12+
if (bytes12(universalAddr) != 0)
13+
revert NotAnEvmAddress(universalAddr);
14+
15+
assembly ("memory-safe") {
16+
addr := universalAddr
1417
}
15-
return address(uint160(uint256(whFormatAddress)));
1618
}

src/Base.sol renamed to src/WormholeRelayer/Base.sol

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
// SPDX-License-Identifier: Apache 2
2-
pragma solidity ^0.8.13;
2+
pragma solidity ^0.8.19;
33

4-
import "./interfaces/IWormholeReceiver.sol";
5-
import "./interfaces/IWormholeRelayer.sol";
6-
import "./interfaces/IWormhole.sol";
7-
import "./Utils.sol";
4+
import "wormhole-sdk/interfaces/IWormholeReceiver.sol";
5+
import "wormhole-sdk/interfaces/IWormholeRelayer.sol";
6+
import "wormhole-sdk/interfaces/IWormhole.sol";
7+
import "wormhole-sdk/Utils.sol";
88

99
abstract contract Base {
1010
IWormholeRelayer public immutable wormholeRelayer;

src/CCTPAndTokenBase.sol renamed to src/WormholeRelayer/CCTPAndTokenBase.sol

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
// SPDX-License-Identifier: Apache 2
2-
pragma solidity ^0.8.13;
2+
pragma solidity ^0.8.19;
33

4-
import "./interfaces/IWormholeReceiver.sol";
5-
import "./interfaces/IWormholeRelayer.sol";
6-
import "./interfaces/ITokenBridge.sol";
7-
import {IERC20} from "./interfaces/IERC20.sol";
8-
import "./interfaces/CCTPInterfaces/ITokenMessenger.sol";
9-
import "./interfaces/CCTPInterfaces/IMessageTransmitter.sol";
4+
import "wormhole-sdk/interfaces/IWormholeReceiver.sol";
5+
import "wormhole-sdk/interfaces/IWormholeRelayer.sol";
6+
import "wormhole-sdk/interfaces/ITokenBridge.sol";
7+
import "wormhole-sdk/interfaces/token/IERC20.sol";
8+
import "wormhole-sdk/interfaces/cctp/ITokenMessenger.sol";
9+
import "wormhole-sdk/interfaces/cctp/IMessageTransmitter.sol";
10+
import "wormhole-sdk/Utils.sol";
1011

11-
import "./Utils.sol";
1212
import "./TokenBase.sol";
1313
import "./CCTPBase.sol";
1414

@@ -216,13 +216,13 @@ abstract contract CCTPAndTokenSender is CCTPAndTokenBase {
216216
token,
217217
amount,
218218
targetChain,
219-
toWormholeFormat(targetAddress),
219+
toUniversalAddress(targetAddress),
220220
0,
221221
payload
222222
);
223223
return
224224
VaaKey({
225-
emitterAddress: toWormholeFormat(address(tokenBridge)),
225+
emitterAddress: toUniversalAddress(address(tokenBridge)),
226226
chainId: wormhole.chainId(),
227227
sequence: sequence
228228
});
@@ -333,7 +333,7 @@ abstract contract CCTPAndTokenReceiver is CCTPAndTokenBase {
333333
) internal view returns (address tokenAddressOnThisChain) {
334334
return
335335
tokenHomeChain == wormhole.chainId()
336-
? fromWormholeFormat(tokenHomeAddress)
336+
? fromUniversalAddress(tokenHomeAddress)
337337
: tokenBridge.wrappedAsset(tokenHomeChain, tokenHomeAddress);
338338
}
339339

@@ -362,7 +362,7 @@ abstract contract CCTPAndTokenReceiver is CCTPAndTokenBase {
362362
ITokenBridge.TransferWithPayload memory transfer = tokenBridge
363363
.parseTransferWithPayload(parsed.payload);
364364
require(
365-
transfer.to == toWormholeFormat(address(this)) &&
365+
transfer.to == toUniversalAddress(address(this)) &&
366366
transfer.toChain == wormhole.chainId(),
367367
"Token was not sent to this address"
368368
);

src/CCTPBase.sol renamed to src/WormholeRelayer/CCTPBase.sol

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
// SPDX-License-Identifier: Apache 2
2-
pragma solidity ^0.8.13;
2+
pragma solidity ^0.8.19;
33

4-
import "./interfaces/IWormholeReceiver.sol";
5-
import "./interfaces/IWormholeRelayer.sol";
6-
import {IERC20} from "./interfaces/IERC20.sol";
7-
import "./interfaces/CCTPInterfaces/ITokenMessenger.sol";
8-
import "./interfaces/CCTPInterfaces/IMessageTransmitter.sol";
4+
import "wormhole-sdk/interfaces/IWormholeReceiver.sol";
5+
import "wormhole-sdk/interfaces/IWormholeRelayer.sol";
6+
import "wormhole-sdk/interfaces/token/IERC20.sol";
7+
import "wormhole-sdk/interfaces/cctp/ITokenMessenger.sol";
8+
import "wormhole-sdk/interfaces/cctp/IMessageTransmitter.sol";
9+
import "wormhole-sdk/Utils.sol";
910

10-
import "./Utils.sol";
1111
import "./Base.sol";
1212

1313
library CCTPMessageLib {

src/TokenBase.sol renamed to src/WormholeRelayer/TokenBase.sol

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
// SPDX-License-Identifier: Apache 2
2-
pragma solidity ^0.8.13;
2+
pragma solidity ^0.8.19;
33

4-
import "./interfaces/IWormholeReceiver.sol";
5-
import "./interfaces/IWormholeRelayer.sol";
6-
import "./interfaces/ITokenBridge.sol";
7-
import {IERC20} from "./interfaces/IERC20.sol";
8-
import {Base} from "./WormholeRelayerSDK.sol";
4+
import "wormhole-sdk/interfaces/IWormholeReceiver.sol";
5+
import "wormhole-sdk/interfaces/IWormholeRelayer.sol";
6+
import "wormhole-sdk/interfaces/ITokenBridge.sol";
7+
import "wormhole-sdk/interfaces/token/IERC20.sol";
8+
import "wormhole-sdk/Utils.sol";
99

10-
import "./Utils.sol";
10+
import {Base} from "./Base.sol";
1111

1212
abstract contract TokenBase is Base {
1313
ITokenBridge public immutable tokenBridge;
@@ -76,13 +76,13 @@ abstract contract TokenSender is TokenBase {
7676
token,
7777
amount,
7878
targetChain,
79-
toWormholeFormat(targetAddress),
79+
toUniversalAddress(targetAddress),
8080
0,
8181
payload
8282
);
8383
return
8484
VaaKey({
85-
emitterAddress: toWormholeFormat(address(tokenBridge)),
85+
emitterAddress: toUniversalAddress(address(tokenBridge)),
8686
chainId: wormhole.chainId(),
8787
sequence: sequence
8888
});
@@ -180,7 +180,7 @@ abstract contract TokenReceiver is TokenBase {
180180
) internal view returns (address tokenAddressOnThisChain) {
181181
return
182182
tokenHomeChain == wormhole.chainId()
183-
? fromWormholeFormat(tokenHomeAddress)
183+
? fromUniversalAddress(tokenHomeAddress)
184184
: tokenBridge.wrappedAsset(tokenHomeChain, tokenHomeAddress);
185185
}
186186

@@ -205,7 +205,7 @@ abstract contract TokenReceiver is TokenBase {
205205
ITokenBridge.TransferWithPayload memory transfer = tokenBridge
206206
.parseTransferWithPayload(parsed.payload);
207207
require(
208-
transfer.to == toWormholeFormat(address(this)) &&
208+
transfer.to == toUniversalAddress(address(this)) &&
209209
transfer.toChain == wormhole.chainId(),
210210
"Token was not sent to this address"
211211
);

src/WormholeRelayerSDK.sol

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
11
// SPDX-License-Identifier: Apache 2
2-
pragma solidity ^0.8.13;
2+
pragma solidity ^0.8.19;
33

4-
import "./interfaces/IWormholeReceiver.sol";
5-
import "./interfaces/IWormholeRelayer.sol";
6-
import "./Chains.sol";
7-
import "./Utils.sol";
8-
import {Base} from "./Base.sol";
9-
import {TokenBase, TokenReceiver, TokenSender} from "./TokenBase.sol";
10-
import {CCTPBase, CCTPReceiver, CCTPSender} from "./CCTPBase.sol";
11-
import {CCTPAndTokenBase, CCTPAndTokenReceiver, CCTPAndTokenSender} from "./CCTPAndTokenBase.sol";
4+
import "wormhole-sdk/interfaces/IWormholeReceiver.sol";
5+
import "wormhole-sdk/interfaces/IWormholeRelayer.sol";
6+
import "wormhole-sdk/Chains.sol";
7+
import "wormhole-sdk/Utils.sol";
8+
9+
import {Base} from "wormhole-sdk/WormholeRelayer/Base.sol";
10+
import {
11+
TokenBase,
12+
TokenReceiver,
13+
TokenSender
14+
} from "wormhole-sdk/WormholeRelayer/TokenBase.sol";
15+
import {
16+
CCTPBase,
17+
CCTPReceiver,
18+
CCTPSender
19+
} from "wormhole-sdk/WormholeRelayer/CCTPBase.sol";
20+
import {
21+
CCTPAndTokenBase,
22+
CCTPAndTokenReceiver,
23+
CCTPAndTokenSender
24+
} from "wormhole-sdk/WormholeRelayer/CCTPAndTokenBase.sol";

0 commit comments

Comments
 (0)