Skip to content

Commit e1c93bf

Browse files
committed
update contracts
1 parent c9808e8 commit e1c93bf

File tree

6 files changed

+78
-46
lines changed

6 files changed

+78
-46
lines changed

README.md

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,36 @@
1-
# Sova Network Contracts
1+
# Sova Contracts
22

3-
This repository contains the smart contracts for the Sova Network. Sova smart contracts can talk directly to Bitcoin and do things like broadcast BTC transactions, decode BTC payloads, and verify signatures.
3+
This repository contains the predeploy contracts for the Sova Network.
4+
5+
Sova smart contracts can communicate directly with Bitcoin and do things like broadcast transactions, decode payloads, verify signatures, get block height and more!
46

57
## Details
68

7-
Sova Network provides direct chain interaction with Bitcoin through custom precompiles, with built-in safeguards against double-spending. Use these precompiles to add Bitcoin composability to your Sova smart contracts.
9+
The Sova Network provides direct communicate with Bitcoin through custom precompiles. The Sova Network uses these precompiles via predeploy contracts. These precompiles come with built-in safeguards against double-spending, payload verification, current block info, and more! These features can be witnessed in action in the `uBTC.sol` native Bitcoin wrapper contract or by importing `SovaBitcoin.sol` to add Bitcoin composability to your Sova smart contracts.
810

9-
### Precompile Contracts
10-
- **L1Block**: Provides Bitcoin block information
11-
- **uBTC**: Bitcoin representation on Sova Network
11+
## Predeploy Contracts
12+
- **SovaL1Block**: Provides Bitcoin block information
13+
- **uBTC**: Native Bitcoin wrapper on the Sova Network
1214

1315
### Libraries
14-
- **SovaBitcoin**: Integration utilities
16+
- **SovaBitcoin**: Sova network utilities
1517

1618
## Build and Test
1719

1820
```shell
1921
# Build the project
2022
forge build
2123

22-
# Run all tests
23-
forge test
24+
```
25+
26+
## Deployed Bytecode verification
27+
28+
Generate the deployed byte code locally to verify the predeploy contract code used on the Sova Network.
29+
30+
```shell
31+
# uBTC.sol
32+
forge inspect src/uBTC.sol:uBTC deployedBytecode
33+
34+
# SovaL1Block.sol
35+
forge inspect src/SovaL1Block.sol:SovaL1Block deployedBytecode
2436
```

script/Counter.s.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// SPDX-License-Identifier: UNLICENSED
2-
pragma solidity 0.8.26;
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity 0.8.15;
33

44
// import {Script, console} from "forge-std/Script.sol";
55
// import {Counter} from "../src/Counter.sol";

src/SovaL1Block.sol

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

44
/**
55
* @title SovaL1Block
66
* @author Sova Labs
7-
* @notice The BitcoinBlock predeploy gives users access to information about the last known
8-
* Bitcoin block. Values within this contract are updated once per Sova block and can
9-
* only be set by the system account. State updates are made by the protocol at the
10-
* beginning of each Sova block.
7+
*
8+
* SovaL1Block provides information about the last known Bitcoin block. Values
9+
* within this contract are updated prior to Sova block execution and can
10+
* only be set by the system account.
1111
*
1212
* @custom:predeploy 0x2100000000000000000000000000000000000015
1313
*/
@@ -21,9 +21,9 @@ contract SovaL1Block {
2121
/// @notice Store the last sova block the values were updated.
2222
uint256 public lastUpdatedBlock;
2323

24-
/// @custom:semver 1.0.0
24+
/// @custom:semver 0.1.0-beta.1
2525
function version() public pure virtual returns (string memory) {
26-
return "1.0.0";
26+
return "0.1.0-beta.1";
2727
}
2828

2929
/// @notice Address of the special depositor account.

src/lib/SovaBitcoin.sol

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
// SPDX-License-Identifier: MIT
2-
pragma solidity 0.8.26;
2+
pragma solidity 0.8.15;
33

44
/**
5-
* @title Sova Bitcoin
5+
* @title SovaBitcoin
66
* @author Sova Labs
7-
* @notice A comprehensive library for integrating with Bitcoin on the Sova EVM.
7+
*
8+
* A library for integrating with native Bitcoin precompiles on Sova.
89
*/
910
library SovaBitcoin {
1011
/// @notice Address of the Bitcoin precompile contract
1112
address private constant BTC_PRECOMPILE = address(0x999);
13+
/// @notice Native Bitcoin wrapper address
14+
address public constant UBTC_ADDRESS = 0x2100000000000000000000000000000000000020;
1215

13-
/// @notice Bitcoin functionality selectors
16+
/// @notice Bitcoin precompile selectors
1417
bytes4 private constant BROADCAST_BYTES = 0x00000001;
1518
bytes4 private constant DECODE_BYTES = 0x00000002;
1619
bytes4 private constant CHECKSIG_BYTES = 0x00000003;
17-
bytes4 private constant BTC_DEPOSIT_ADDR_BYTES = 0x00000004;
20+
bytes4 private constant ADDRESS_CONVERT_LEADING_BYTES = 0x00000004;
1821
bytes4 private constant CREATE_AND_SIGN_BYTES = 0x00000005;
1922

20-
/// @notice Bitcoin deposit address for the current network
21-
address public constant UBTC_ADDRESS = 0x2100000000000000000000000000000000000020;
22-
2323
struct Output {
2424
string addr;
2525
uint256 value;
@@ -43,12 +43,20 @@ library SovaBitcoin {
4343
error PrecompileCallFailed();
4444
error InvalidOutput(string expected, string actual);
4545
error InsufficientDeposit();
46+
error InvalidDeposit();
4647
error InsufficientInput();
4748
error InvalidLocktime();
4849

50+
/// @custom:semver 0.1.0-beta.1
51+
function version() public pure returns (string memory) {
52+
return "0.1.0-beta.1";
53+
}
54+
4955
/**
5056
* @notice Decodes a raw Bitcoin transaction into a structured format
57+
*
5158
* @param signedTx The raw signed Bitcoin transaction
59+
*
5260
* @return BitcoinTx Object containing the decoded transaction data
5361
*/
5462
function decodeBitcoinTx(bytes memory signedTx) internal view returns (BitcoinTx memory) {
@@ -59,26 +67,32 @@ library SovaBitcoin {
5967

6068
/**
6169
* @notice Verifies the signatures in a Bitcoin transaction
70+
*
6271
* @param signedTx The raw signed Bitcoin transaction
72+
*
6373
* @return success Boolean indicating if payload is valid
6474
*/
6575
function checkSignature(bytes calldata signedTx) internal view returns (bool success) {
6676
(success,) = BTC_PRECOMPILE.staticcall(abi.encodePacked(CHECKSIG_BYTES, signedTx));
6777
}
6878

6979
/**
70-
* @notice Gets the Bitcoin deposit address for the current network
71-
* @return returnData The Bitcoin address where the network receives deposits
80+
* @notice Retrieves the unique deposit address for the corresponding EVM address
81+
*
82+
* @param addr The EVM address to convert
83+
*
84+
* @return returnData The Bitcoin deposit address in bytes format
7285
*/
73-
function getBtcNetworkReceive() internal returns (bytes memory) {
74-
(bool success, bytes memory returndata) =
75-
BTC_PRECOMPILE.call(abi.encodePacked(BTC_DEPOSIT_ADDR_BYTES, UBTC_ADDRESS));
86+
function convertToBtcAddress(address addr) internal returns (bytes memory) {
87+
(bool success, bytes memory returnData) =
88+
BTC_PRECOMPILE.call(abi.encodePacked(ADDRESS_CONVERT_LEADING_BYTES, addr));
7689
if (!success) revert PrecompileCallFailed();
77-
return returndata;
90+
return returnData;
7891
}
7992

8093
/**
8194
* @notice Broadcasts a signed Bitcoin transaction to the Bitcoin network
95+
*
8296
* @param signedTx The raw signed Bitcoin transaction to broadcast
8397
*/
8498
function broadcastBitcoinTx(bytes memory signedTx) internal {
@@ -88,11 +102,13 @@ library SovaBitcoin {
88102

89103
/**
90104
* @notice Signs and broadcasts a Bitcoin transaction from the specified signer.
105+
*
91106
* @param signer The address of the entity signing the transaction
92107
* @param amount The amount in satoshis to send
93108
* @param btcGasLimit Specified gas limit for the Bitcoin transaction (in satoshis)
94109
* @param blockHeight The current Bitcoin block height for indexing purposes
95110
* @param destinationAddress Bitcoin address receiving the funds
111+
*
96112
* @return txid Bitcoin transaction ID
97113
*/
98114
function vaultSpend(
@@ -120,17 +136,22 @@ library SovaBitcoin {
120136
* 4. Validates the locktime is not in the future
121137
* 5. Checks that the first output address matches the network's receive address
122138
*
123-
* @param signedTx The raw signed Bitcoin transaction
124-
* @param amount The minimum expected amount in satoshis
125-
* @return btcTx The decoded Bitcoin transaction if all validations pass
139+
* @param signedTx The raw signed Bitcoin transaction
140+
* @param amount The minimum expected amount in satoshis
141+
*
142+
* @return btcTx The decoded Bitcoin transaction
126143
*/
127-
function isDepositBtc(bytes memory signedTx, uint256 amount) internal returns (BitcoinTx memory) {
144+
function isValidDeposit(bytes memory signedTx, uint256 amount) internal returns (BitcoinTx memory) {
128145
BitcoinTx memory btcTx = decodeBitcoinTx(signedTx);
129146

130147
if (btcTx.outputs.length < 1 || btcTx.outputs.length > 3 || btcTx.outputs[0].value < amount) {
131148
revert InsufficientDeposit();
132149
}
133150

151+
if (btcTx.outputs[0].value != amount) {
152+
revert InvalidDeposit();
153+
}
154+
134155
if (btcTx.inputs.length < 1) {
135156
revert InsufficientInput();
136157
}
@@ -139,10 +160,11 @@ library SovaBitcoin {
139160
revert InvalidLocktime();
140161
}
141162

142-
bytes memory recipientBtcAddress = getBtcNetworkReceive();
163+
// Recover the callers unique bitcoin deposit address
164+
bytes memory convertedBtcAddress = SovaBitcoin.convertToBtcAddress(msg.sender);
143165

144-
if (keccak256(recipientBtcAddress) != keccak256(bytes(btcTx.outputs[0].addr))) {
145-
revert InvalidOutput(btcTx.outputs[0].addr, string(recipientBtcAddress));
166+
if (keccak256(convertedBtcAddress) != keccak256(bytes(btcTx.outputs[0].addr))) {
167+
revert InvalidOutput(btcTx.outputs[0].addr, string(convertedBtcAddress));
146168
}
147169

148170
return btcTx;

src/uBTC.sol

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: MIT
2-
pragma solidity 0.8.26;
2+
pragma solidity 0.8.15;
33

44
import "solady/auth/Ownable.sol";
55
import "solady/tokens/WETH.sol";
@@ -9,14 +9,12 @@ import "./lib/SovaBitcoin.sol";
99
/**
1010
* @title Universal Bitcoin Token (uBTC)
1111
* @author Sova Labs
12-
* @notice Bitcoin meets ERC20. Bitcoin meets composability.
12+
*
13+
* Bitcoin meets ERC20. Bitcoin meets composability.
1314
*
1415
* @custom:predeploy 0x2100000000000000000000000000000000000020
1516
*/
1617
contract uBTC is WETH, Ownable {
17-
/**
18-
* @notice Error codes
19-
*/
2018
error InsufficientDeposit();
2119
error InsufficientInput();
2220
error InsufficientAmount();
@@ -74,7 +72,7 @@ contract uBTC is WETH, Ownable {
7472
}
7573

7674
// Validate if the transaction is a network deposit and get the decoded tx
77-
SovaBitcoin.BitcoinTx memory btcTx = SovaBitcoin.isDepositBtc(signedTx, amount);
75+
SovaBitcoin.BitcoinTx memory btcTx = SovaBitcoin.isValidDeposit(signedTx, amount);
7876

7977
// Check if signature is valid and the inputs are unspent
8078
if (!SovaBitcoin.checkSignature(signedTx)) {

test/Counter.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: MIT
2-
pragma solidity 0.8.26;
2+
pragma solidity 0.8.15;
33

44
import {Test, console} from "forge-std/Test.sol";
55
import {uBTC} from "../src/uBTC.sol";

0 commit comments

Comments
 (0)