Sapphire Contracts Lib
A library for privacy focused smart contract development.
- Implementations of OPL smart contracts
- Sapphire library precompiles and cryptographic primitives
- Wrapped Rose example
Overview
Installation
$ pnpm install @oasisprotocol/sapphire-contracts
Usage
Once installed, you can import and use the Sapphire contracts as follows:
pragma solidity ^0.8.13;
import "@oasisprotocol/sapphire-contracts/contracts/Sapphire.sol";
contract RandomNumber {
function generateNumber() public view returns (uint) {
return uint(bytes32(Sapphire.randomBytes(32, "")));
}
}
Documentation
See the user's guide for Sapphire and OPL.
The generated API reference is hosted at api.docs.oasis.io.
Generating API docs locally requires Foundry and mdbook-pagetoc. To install them and generate the docs execute:
curl -L https://foundry.paradigm.xyz | bash
cargo install mdbook-pagetoc
pnpm doc
The API docs index will be located in sol/sapphire-contracts/book/index.html
.
Contribute
There are many ways you can participate and help build high quality software. Check out the contribution guide!
Contents
A13e
This is the interface for universal authentication mechanism (e.g. SIWE):
- The user-facing app calls login() to generate the bearer token on-chain.
- Any smart contract method that requires authentication accept this token as an argument. Then, it passes the token to authMsgSender() to verify it and obtain the authenticated user address. This address can then serve as a user ID for authorization.
State Variables
_revokedBearers
A mapping of revoked bearers. Access it directly or use the checkRevokedBearer modifier.
mapping(bytes32 => bool) internal _revokedBearers;
Functions
checkRevokedBearer
Reverts if the given bearer was revoked
modifier checkRevokedBearer(bytes calldata bearer);
login
Verify the login message and its signature and generate the bearer token.
function login(string calldata message, SignatureRSV calldata sig) external view virtual returns (bytes memory);
authMsgSender
Validate the bearer token and return authenticated msg.sender.
function authMsgSender(bytes calldata bearer) internal view virtual returns (address);
revokeBearer
Revoke the bearer token with the corresponding hash. e.g. In case when the bearer token is leaked or for extra-secure apps on every logout.
function revokeBearer(bytes32 bearer) internal;
Errors
RevokedBearer
The bearer token was revoked
error RevokedBearer();
Bearer
struct Bearer {
string domain;
address userAddr;
uint256 validUntil;
}
SiweAuth
Inherits: A13e
Inherit this contract, if you wish to enable SIWE-based authentication for your contract methods that require authenticated calls. The smart contract needs to be bound to a domain (passed in constructor).
Example
contract MyContract is SiweAuth {
address private _owner;
modifier onlyOwner(bytes calldata bearer) {
if (authMsgSender(bearer) != _owner) {
revert("not allowed");
}
_;
}
constructor(string memory domain) SiweAuth(domain) {
_owner = msg.sender;
}
function getSecretMessage(bytes calldata bearer) external view onlyOwner(bearer) returns (string memory) {
return "Very secret message";
}
}
State Variables
_domain
Domain which the dApp is associated with
string private _domain;
_bearerEncKey
Encryption key which the bearer tokens are encrypted with
bytes32 private _bearerEncKey;
DEFAULT_VALIDITY
Default bearer token validity, if no expiration-time provided
uint256 private constant DEFAULT_VALIDITY = 24 hours;
Functions
constructor
Instantiate the contract which uses SIWE for authentication and runs on the specified domain.
constructor(string memory inDomain);
login
function login(string calldata siweMsg, SignatureRSV calldata sig) external view override returns (bytes memory);
domain
Return the domain associated with the dApp.
function domain() public view returns (string memory);
authMsgSender
function authMsgSender(bytes calldata bearer) internal view override checkRevokedBearer(bearer) returns (address);
Errors
ChainIdMismatch
Chain ID in the SIWE message does not match the actual chain ID
error ChainIdMismatch();
DomainMismatch
Domain in the SIWE message does not match the domain of a dApp
error DomainMismatch();
AddressMismatch
User address in the SIWE message does not match the message signer's address
error AddressMismatch();
NotBeforeInFuture
The Not before value in the SIWE message is still in the future
error NotBeforeInFuture();
Expired
The bearer token validity or the Expires value in the SIWE message is in the past
error Expired();
Contents
- Enclave
- AutoConfigUnavailable
- MissingRemoteAddr
- MissingRemoteChainId
- SelfCallDisallowed
- UnknownEndpoint
- Result
- ICelerMessageBus
- BaseEndpoint
- Endpoint
- _getRemoteChainId
- _getChainConfig
- autoswitch
- _getBus
- _chainName2ChainId
- Host
Enclave
Inherits: Endpoint
The Sapphire-side of an OPL dApp.
Functions
constructor
constructor(address _host, bytes32 _hostChain) Endpoint(_host, _hostChain);
AutoConfigUnavailable
Unable to automatically configure OPL. Please use the manual version of the base contract.
error AutoConfigUnavailable();
MissingRemoteAddr
The remote endpoint's contract address was missing.
error MissingRemoteAddr();
MissingRemoteChainId
The remote endpoint's chain ID was missing.
error MissingRemoteChainId();
SelfCallDisallowed
Calls to contracts on the same chain are not allowed unless on a local testnet.
error SelfCallDisallowed();
UnknownEndpoint
The requested endpoint does not exist.
error UnknownEndpoint();
Result
The outcome of the message call.
enum Result {
PermanentFailure,
TransientFailure,
Success
}
ICelerMessageBus
Functions
feeBase
function feeBase() external view returns (uint256);
feePerByte
function feePerByte() external view returns (uint256);
sendMessage
function sendMessage(address _host, uint256 _hostChainId, bytes calldata _message) external payable;
BaseEndpoint
State Variables
messageBus
address internal immutable messageBus;
inOrder
bool private immutable inOrder;
remote
address private remote;
remoteChainId
uint256 private remoteChainId;
endpoints
mapping(bytes32 => function(bytes calldata) returns (Result)) private endpoints;
txSeq
uint256 private txSeq;
rxSeq
uint256 private rxSeq;
Functions
constructor
constructor(address _remote, uint256 _remoteChainId, address _messageBus, bool _inOrder);
registerEndpoint
function registerEndpoint(bytes memory _method, function(bytes calldata) returns (Result) _cb) internal;
postMessage
function postMessage(bytes memory _method) internal returns (uint256);
postMessage
Calls the remote endpoint, returning the amount of native token charged for the operation.
function postMessage(bytes memory _method, bytes memory _message) internal returns (uint256);
executeMessage
Celer message bus callback function.
function executeMessage(address _sender, uint64 _senderChainId, bytes calldata _message, address)
external
payable
returns (uint256);
estimateFee
function estimateFee(uint256 _msgLen) internal view returns (uint256);
_isLocalNetwork
function _isLocalNetwork() internal view returns (bool);
Endpoint
Inherits: BaseEndpoint
An app that sends or receives using OPL.
Functions
constructor
constructor(address _remote, bytes32 _remoteChainName)
BaseEndpoint(_remote, _getRemoteChainId(_remoteChainName), _getBus(_remote, _remoteChainName), false);
_getRemoteChainId
function _getRemoteChainId(bytes32 _remoteChainName) view returns (uint256);
_getChainConfig
Configs from https://im-docs.celer.network/developer/contract-addresses-and-rpc-info.
function _getChainConfig(uint256 _chainId) pure returns (address _messageBus, bool _isTestnet);
autoswitch
Autoswitch automatically picks the remote network based on the network the contract on which the contract has already been deployed. When on testnet, the remote chain will be the testnet version of the provided chain. When running locally, the remote chain will be this one and the contracts will call each other without going through a message bus. This is helpful for debugging logic but does not test gas fee payment and other moving parts.
function autoswitch(bytes32 protocol) view returns (bytes32 networkName);
_getBus
function _getBus(address _remote, bytes32 _remoteChainName) view returns (address);
_chainName2ChainId
function _chainName2ChainId(bytes32 name) pure returns (uint256);
Host
Inherits: Endpoint
The L1-side of an OPL dApp.
Functions
constructor
constructor(address _enclave) Endpoint(_enclave, autoswitch("sapphire"));
Contents
Contents
SiweAuthTests
Inherits: SiweAuth
State Variables
_owner
address private _owner;
Functions
constructor
constructor(string memory domain) SiweAuth(domain);
testVerySecretMessage
function testVerySecretMessage(bytes calldata bearer) external view returns (string memory);
testLogin
function testLogin(string calldata message, SignatureRSV calldata sig) external view returns (bytes memory);
testAuthMsgSender
function testAuthMsgSender(bytes calldata bearer) external view returns (address);
testRevokeBearer
function testRevokeBearer(bytes32 bearer) external;
doNothing
function doNothing() external;
CBOR_InvalidKey
While parsing CBOR map, unexpected key
error CBOR_InvalidKey();
CBOR_InvalidMap
While parsing CBOR map, length is invalid, or other parse error
error CBOR_InvalidMap();
CBOR_InvalidLength
While parsing CBOR structure, data length was unexpected
error CBOR_InvalidLength(uint256);
CBOR_InvalidUintPrefix
Value cannot be parsed as a uint
error CBOR_InvalidUintPrefix(uint8);
CBOR_InvalidUintSize
CBOR spec supports, 1, 2, 4 & 8 byte uints. Caused by parse error.
error CBOR_InvalidUintSize(uint8);
CBOR_Error_ValueOutOfRange
CBOR parsed value is out of expected range
error CBOR_Error_ValueOutOfRange(uint256 value, uint256 maxValue);
CBOR_Error_BufferOverrun
Buffer too short to parse expected value
error CBOR_Error_BufferOverrun(uint256 len, uint256 offset, uint256 need);
CBOR_Error_BytesTooLong
Byte array is too long
Solidity has 256bit length prefixes for byte arrays. We decided for a reasonable cutoff point (64kb), so at most a 2-byte uint describing the array length.
error CBOR_Error_BytesTooLong(uint256 byteLength);
parseUint
function parseUint(bytes memory result, uint256 offset) pure returns (uint256 newOffset, uint256 value);
encodeBytes
function encodeBytes(bytes memory in_bytes) pure returns (bytes memory out_cbor);
parseUint128
function parseUint128(bytes memory result, uint256 offset) pure returns (uint256 newOffset, uint128 value);
parseMapStart
function parseMapStart(bytes memory in_data, uint256 in_offset) pure returns (uint256 n_entries, uint256 out_offset);
parseUint64
function parseUint64(bytes memory result, uint256 offset) pure returns (uint256 newOffset, uint64 value);
parseKey
function parseKey(bytes memory result, uint256 offset) pure returns (uint256 newOffset, bytes32 keyDigest);
encodeUint
we don't follow bignum tagged encoding See: https://www.rfc-editor.org/rfc/rfc8949.html#section-3.4.3
function encodeUint(uint256 value) pure returns (bytes memory);
_deriveKey
function _deriveKey(bytes32 in_peerPublicKey, Sapphire.Curve25519SecretKey in_x25519_secret) view returns (bytes32);
_encryptInner
function _encryptInner(
bytes memory in_data,
Sapphire.Curve25519SecretKey in_x25519_secret,
bytes15 nonce,
bytes32 peerPublicKey
) view returns (bytes memory out_encrypted);
function encryptCallData
encryptCallData(bytes)
function encryptCallData(bytes memory in_data) view returns (bytes memory out_encrypted);
encryptCallData(bytes, Sapphire.Curve25519PublicKey, Sapphire.Curve25519SecretKey, bytes15, uint256, bytes32)
function encryptCallData(
bytes memory in_data,
Sapphire.Curve25519PublicKey myPublic,
Sapphire.Curve25519SecretKey mySecret,
bytes15 nonce,
uint256 epoch,
bytes32 peerPublicKey
) view returns (bytes memory out_encrypted);
StakingAddress
21 byte version-prefixed address (1 byte version, 20 bytes truncated digest).
type StakingAddress is bytes21;
StakingSecretKey
32 byte secret key.
type StakingSecretKey is bytes32;
ConsensusUtils
Generate Oasis wallets for use with staking at the consensus level.
State Variables
ADDRESS_V0_CONTEXT_IDENTIFIER
The unique context for v0 staking account addresses.
Note: see: @oasisprotocol/oasis-core :: go/staking/api/address.go
string private constant ADDRESS_V0_CONTEXT_IDENTIFIER = "oasis-core/address: staking";
ADDRESS_V0_CONTEXT_VERSION
uint8 private constant ADDRESS_V0_CONTEXT_VERSION = 0;
Functions
generateStakingAddress
Generate a random Ed25519 wallet for Oasis consensus-layer staking.
function generateStakingAddress(bytes memory personalization)
internal
view
returns (StakingAddress publicAddress, StakingSecretKey secretKey);
Parameters
Name | Type | Description |
---|---|---|
personalization | bytes | Optional user-specified entropy. |
Returns
Name | Type | Description |
---|---|---|
publicAddress | StakingAddress | Public address of the keypair. |
secretKey | StakingSecretKey | Secret key for the keypair. |
_stakingAddressFromPublicKey
Derive the staking address from the public key.
function _stakingAddressFromPublicKey(bytes32 ed25519publicKey) internal view returns (bytes21);
Parameters
Name | Type | Description |
---|---|---|
ed25519publicKey | bytes32 | Ed25519 public key. |
_addressFromData
Derive an Oasis-style address.
function _addressFromData(string memory contextIdentifier, uint8 contextVersion, bytes memory data)
internal
view
returns (bytes21);
Parameters
Name | Type | Description |
---|---|---|
contextIdentifier | string | Domain separator. |
contextVersion | uint8 | Domain version. |
data | bytes | Public point of the keypair. |
DateTime
Considers leap year, but not leap second.
Note: attribution: https://github.com/pipermerriam/ethereum-datetime/blob/master/contracts/contracts/DateTime.sol
State Variables
ORIGIN_YEAR
uint16 private constant ORIGIN_YEAR = 1970;
Functions
isLeapYear
function isLeapYear(uint16 year) internal pure returns (bool);
toTimestamp
Convert year, month, day, hour, minute, second to Unix timestamp.
Leap second is not supported.
function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute, uint8 second)
internal
pure
returns (uint256 timestamp);
EIP1559Signer
Functions
encodeUnsignedTx
Encode an unsigned EIP-1559 transaction for signing
function encodeUnsignedTx(EIP1559Tx memory rawTx) internal pure returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
rawTx | EIP1559Tx | Transaction to encode |
encodeSignedTx
Encode a signed EIP-1559 transaction
function encodeSignedTx(EIP1559Tx memory rawTx, SignatureRSV memory rsv) internal pure returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
rawTx | EIP1559Tx | Transaction which was signed |
rsv | SignatureRSV | R, S & V parameters of signature |
signRawTx
Sign a raw transaction
function signRawTx(EIP1559Tx memory rawTx, address pubkeyAddr, bytes32 secretKey)
internal
view
returns (SignatureRSV memory ret);
Parameters
Name | Type | Description |
---|---|---|
rawTx | EIP1559Tx | Transaction to sign |
pubkeyAddr | address | Ethereum address of secret key |
secretKey | bytes32 | Secret key used to sign |
sign
Sign a transaction, returning it in EIP-1559 encoded form
function sign(address publicAddress, bytes32 secretKey, EIP1559Tx memory transaction)
internal
view
returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
publicAddress | address | Ethereum address of secret key |
secretKey | bytes32 | Secret key used to sign |
transaction | EIP1559Tx | Transaction to sign |
Structs
EIP1559Tx
struct EIP1559Tx {
uint64 nonce;
uint256 maxPriorityFeePerGas;
uint256 maxFeePerGas;
uint64 gasLimit;
address to;
uint256 value;
bytes data;
EIPTypes.AccessList accessList;
uint256 chainId;
}
EIP155Signer
Functions
encodeSignedTx
Encode a signed EIP-155 transaction.
function encodeSignedTx(EthTx memory rawTx, SignatureRSV memory rsv) internal pure returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
rawTx | EthTx | Transaction which was signed. |
rsv | SignatureRSV | R, S & V parameters of signature. |
signRawTx
Sign a raw transaction, which will then need to be encoded to include the signature.
function signRawTx(EthTx memory rawTx, address pubkeyAddr, bytes32 secretKey)
internal
view
returns (SignatureRSV memory ret);
Parameters
Name | Type | Description |
---|---|---|
rawTx | EthTx | Transaction to sign. |
pubkeyAddr | address | Ethereum address of secret key. |
secretKey | bytes32 | Secret key used to sign. |
sign
Sign a transaction, returning it in EIP-155 encoded form.
function sign(address publicAddress, bytes32 secretKey, EthTx memory transaction)
internal
view
returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
publicAddress | address | Ethereum address of secret key. |
secretKey | bytes32 | Secret key used to sign. |
transaction | EthTx | Transaction to sign. |
Structs
EthTx
struct EthTx {
uint64 nonce;
uint256 gasPrice;
uint64 gasLimit;
address to;
uint256 value;
bytes data;
uint256 chainId;
}
EIP2930Signer
Functions
encodeUnsignedTx
Encode an unsigned EIP-2930 transaction for signing
function encodeUnsignedTx(EIP2930Tx memory rawTx) internal pure returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
rawTx | EIP2930Tx | Transaction to encode |
encodeSignedTx
Encode a signed EIP-2930 transaction
function encodeSignedTx(EIP2930Tx memory rawTx, SignatureRSV memory rsv) internal pure returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
rawTx | EIP2930Tx | Transaction which was signed |
rsv | SignatureRSV | R, S & V parameters of signature |
signRawTx
Sign a raw transaction
function signRawTx(EIP2930Tx memory rawTx, address pubkeyAddr, bytes32 secretKey)
internal
view
returns (SignatureRSV memory ret);
Parameters
Name | Type | Description |
---|---|---|
rawTx | EIP2930Tx | Transaction to sign |
pubkeyAddr | address | Ethereum address of secret key |
secretKey | bytes32 | Secret key used to sign |
sign
Sign a transaction, returning it in EIP-2930 encoded form
function sign(address publicAddress, bytes32 secretKey, EIP2930Tx memory transaction)
internal
view
returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
publicAddress | address | Ethereum address of secret key |
secretKey | bytes32 | Secret key used to sign |
transaction | EIP2930Tx | Transaction to sign |
Structs
EIP2930Tx
struct EIP2930Tx {
uint64 nonce;
uint256 gasPrice;
uint64 gasLimit;
address to;
uint256 value;
bytes data;
EIPTypes.AccessList accessList;
uint256 chainId;
}
EIPTypes
Functions
encodeAccessList
Encode an access list for EIP-1559 and EIP-2930 transactions
function encodeAccessList(AccessList memory list) internal pure returns (bytes memory);
Structs
AccessList
struct AccessList {
AccessListItem[] items;
}
AccessListItem
struct AccessListItem {
address addr;
bytes32[] storageKeys;
}
SignatureRSV
struct SignatureRSV {
bytes32 r;
bytes32 s;
uint256 v;
}
EthereumUtils
State Variables
K256_P
uint256 internal constant K256_P = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f;
K256_P_PLUS_1_OVER_4
uint256 internal constant K256_P_PLUS_1_OVER_4 = 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0c;
PRECOMPILE_BIGMODEXP
address internal constant PRECOMPILE_BIGMODEXP = address(0x5);
Functions
expmod
function expmod(uint256 base, uint256 exponent, uint256 modulus) internal view returns (uint256 out);
k256DeriveY
Recover Y coordinate from X coordinate and sign bit.
function k256DeriveY(uint8 prefix, uint256 x) internal view returns (uint256 y);
Parameters
Name | Type | Description |
---|---|---|
prefix | uint8 | 0x02 or 0x03 indicates sign bit of compressed point. |
x | uint256 | X coordinate. |
k256Decompress
Decompress SEC P256 k1 point.
function k256Decompress(bytes memory pk) internal view returns (uint256 x, uint256 y);
Parameters
Name | Type | Description |
---|---|---|
pk | bytes | 33 byte compressed public key. |
Returns
Name | Type | Description |
---|---|---|
x | uint256 | X coordinate. |
y | uint256 | Y coordinate. |
k256PubkeyToEthereumAddress
function k256PubkeyToEthereumAddress(bytes memory pubkey) internal view returns (address);
toEthereumAddress
Convert SEC P256 k1 curve point to Ethereum address.
Note: see: https://gavwood.com/paper.pdf (pp. 212)
function toEthereumAddress(uint256 x, uint256 y) internal pure returns (address);
Parameters
Name | Type | Description |
---|---|---|
x | uint256 | X coordinate. |
y | uint256 | Y coordinate. |
splitDERSignature
Extracts the r
and s
parameters from a DER encoded ECDSA
signature.
The signature is an ASN1 encoded SEQUENCE of the variable length r
and
s
INTEGERs.
| 0x30 | len(z) | 0x02 | len(r) | r | 0x02 | len(s) | s | = hex value
| 1 | 1 | 1 | 1 | 1-33 | 1 | 1 | 1-33 | = byte length
If the highest bit of either r
or s
is set, it will be prefix padded
with a zero byte. There is exponentially decreasing probability that
either r
or s
will be below 32 bytes. There is a very high
probability that either r
or s
will be 33 bytes. This function only
works if either r
or s
are 256bits or lower.
Note: see: https://bitcoin.stackexchange.com/questions/58853/how-do-you-figure-out-the-r-and-s-out-of-a-signature-using-python
function splitDERSignature(bytes memory der) internal pure returns (SignatureRSV memory rsv);
Parameters
Name | Type | Description |
---|---|---|
der | bytes | DER encoded ECDSA signature |
Returns
Name | Type | Description |
---|---|---|
rsv | SignatureRSV | ECDSA R point X coordinate, and S scalar |
recoverV
function recoverV(address pubkeyAddr, bytes32 digest, SignatureRSV memory rsv) internal pure;
toEthereumSignature
Convert a Secp256k1PrehashedKeccak256 signature to one accepted by ecrecover.
Note: see: https://gavwood.com/paper.pdf (pp. 206)
function toEthereumSignature(bytes memory pubkey, bytes32 digest, bytes memory signature)
internal
view
returns (address pubkeyAddr, SignatureRSV memory rsv);
Parameters
Name | Type | Description |
---|---|---|
pubkey | bytes | 33 byte compressed public key. |
digest | bytes32 | 32 byte pre-hashed message digest. |
signature | bytes | ASN.1 DER encoded signature, as returned from Sapphire.sign . |
Returns
Name | Type | Description |
---|---|---|
pubkeyAddr | address | 20 byte Ethereum address. |
rsv | SignatureRSV | Ethereum EcDSA RSV signature values. |
sign
function sign(address pubkeyAddr, bytes32 secretKey, bytes32 digest) internal view returns (SignatureRSV memory rsv);
generateKeypair
Generate an Ethereum compatible SEC P256 k1 keypair and corresponding public address.
function generateKeypair() internal view returns (address pubkeyAddr, bytes32 secretKey);
Returns
Name | Type | Description |
---|---|---|
pubkeyAddr | address | Ethereum address. |
secretKey | bytes32 | Secret key used for signing. |
Errors
expmod_Error
error expmod_Error();
k256DeriveY_Invalid_Prefix_Error
error k256DeriveY_Invalid_Prefix_Error();
k256Decompress_Invalid_Length_Error
error k256Decompress_Invalid_Length_Error();
DER_Split_Error
error DER_Split_Error();
recoverV_Error
error recoverV_Error();
RLPWriter
Author: RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor modifications to improve legibility.
Notes:
-
attribution: https://github.com/bakaoh/solidity-rlp-encode
-
attribution: https://raw.githubusercontent.com/Maia-DAO/solidity-rlp-encoder/main/rlp/RLPWriter.sol
Functions
writeBytes
RLP encodes a byte string.
function writeBytes(bytes memory _in) internal pure returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
_in | bytes | The byte string to encode. |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes | The RLP encoded string in bytes. |
writeList
RLP encodes a list of RLP encoded byte byte strings.
function writeList(bytes memory _in) internal pure returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
_in | bytes | The RLP encoded byte strings. |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes | The RLP encoded list of items in bytes. |
writeList
RLP encodes a list of RLP encoded byte byte strings.
function writeList(bytes[] memory _in) internal pure returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
_in | bytes[] | The list of RLP encoded byte strings. |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes | The RLP encoded list of items in bytes. |
writeString
RLP encodes a string.
function writeString(string memory _in) internal pure returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
_in | string | The string to encode. |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes | The RLP encoded string in bytes. |
writeAddress
RLP encodes an address.
function writeAddress(address _in) internal pure returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
_in | address | The address to encode. |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes | The RLP encoded address in bytes. |
writeUint
RLP encodes a uint.
function writeUint(uint256 _in) internal pure returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
_in | uint256 | The uint256 to encode. |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes | The RLP encoded uint256 in bytes. |
writeBool
RLP encodes a bool.
function writeBool(bool _in) internal pure returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
_in | bool | The bool to encode. |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes | The RLP encoded bool in bytes. |
_writeLength
Encode the first byte and then the len
in binary form if
length
is more than 55.
function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
_len | uint256 | The length of the string or the payload. |
_offset | uint256 | 128 if item is string, 192 if item is list. |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes | RLP encoded bytes. |
_toBinary
Encode integer in big endian binary form with no leading zeroes.
function _toBinary(uint256 _x) private pure returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
_x | uint256 | The integer to encode. |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes | RLP encoded bytes. |
_memcpy
Copies a piece of memory to another location.
Note: attribution: https://github.com/Arachnid/solidity-stringutils
function _memcpy(uint256 _dest, uint256 _src, uint256 _len) private pure;
Parameters
Name | Type | Description |
---|---|---|
_dest | uint256 | Destination location. |
_src | uint256 | Source location. |
_len | uint256 | Length of memory to copy. |
_flatten
Flattens a list of byte strings into one byte string.
Note: attribution: https://github.com/sammayo/solidity-rlp-encoder
function _flatten(bytes[] memory _list) private pure returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
_list | bytes[] | List of byte strings to flatten. |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes | The flattened byte string. |
Sapphire
This library provides a number of convenient wrappers for cryptographic operations such as the x25519 key derivation, Deoxys-II-based encryption and decryption, signing key generation, message digest signing and verification, gas padding and hashing. Most of the mentioned functions are implemented as Sapphire's precompiles and are cheap to call.
Calling Precompiles Manually
You can override the wrappers and call Sapphire precompiles by dispatching
calls to specific well-known contract addresses, as described below. The
Precompile address section of each function will show you the address
of the corresponding precompile.
Input parameters should be packed into a contiguous memory region with each
chunk of data padded to 32 bytes as usual. The recommended way to construct
parameter byte sequences in Solidity is with abi.encode
and abi.decode
,
which will transparently handle things like putting bytes
lengths in the
correct position.
State Variables
RANDOM_BYTES
address internal constant RANDOM_BYTES = 0x0100000000000000000000000000000000000001;
DERIVE_KEY
address internal constant DERIVE_KEY = 0x0100000000000000000000000000000000000002;
ENCRYPT
address internal constant ENCRYPT = 0x0100000000000000000000000000000000000003;
DECRYPT
address internal constant DECRYPT = 0x0100000000000000000000000000000000000004;
GENERATE_SIGNING_KEYPAIR
address internal constant GENERATE_SIGNING_KEYPAIR = 0x0100000000000000000000000000000000000005;
SIGN_DIGEST
address internal constant SIGN_DIGEST = 0x0100000000000000000000000000000000000006;
VERIFY_DIGEST
address internal constant VERIFY_DIGEST = 0x0100000000000000000000000000000000000007;
CURVE25519_PUBLIC_KEY
address internal constant CURVE25519_PUBLIC_KEY = 0x0100000000000000000000000000000000000008;
GAS_USED
address internal constant GAS_USED = 0x0100000000000000000000000000000000000009;
PAD_GAS
address internal constant PAD_GAS = 0x010000000000000000000000000000000000000a;
SHA512_256
address internal constant SHA512_256 = 0x0100000000000000000000000000000000000101;
SHA512
address internal constant SHA512 = 0x0100000000000000000000000000000000000102;
SHA384
address internal constant SHA384 = 0x0100000000000000000000000000000000000104;
Functions
randomBytes
Generate num_bytes
pseudo-random bytes, with an optional
personalization string (pers
) added into the hashing algorithm to
increase domain separation when needed.
Precompile address
0x0100000000000000000000000000000000000001
Gas cost
10,000 minimum plus 240 per output word plus 60 per word of the personalization string.
Implementation details
The mode (e.g. simulation or "view call" vs transaction execution) is fed to TupleHash (among other block-dependent components) to derive the "key id", which is then used to derive a per-block VRF key from epoch-ephemeral entropy (using KMAC256 and cSHAKE) so a different key id will result in a unique per-block VRF key. This per-block VRF key is then used to create the per-block root RNG which is then used to derive domain-separated (using Merlin transcripts) per-transaction random RNGs which are then exposed via this precompile. The KMAC, cSHAKE and TupleHash algorithms are SHA-3 derived functions defined in NIST Special Publication 800-185.
DANGER: Prior to Sapphire ParaTime 0.6.0
All view queries and simulated transactions (via eth_call
) would
receive the same entropy in-between blocks if they use the same
num_bytes
and pers
parameters. If your contract requires
confidentiality you should generate a secret in the constructor to be
used with view calls:
Sapphire.randomBytes(64, abi.encodePacked(msg.sender, this.perContactSecret));
Example
bytes memory randomPad = Sapphire.randomBytes(64, "");
function randomBytes(uint256 numBytes, bytes memory pers) internal view returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
numBytes | uint256 | The number of bytes to return. |
pers | bytes | An optional personalization string to increase domain separation. |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes | The random bytes. If the number of bytes requested is too large (over 1024), a smaller amount (1024) will be returned. |
generateCurve25519KeyPair
Generates a Curve25519 keypair.
function generateCurve25519KeyPair(bytes memory pers)
internal
view
returns (Curve25519PublicKey pk, Curve25519SecretKey sk);
Parameters
Name | Type | Description |
---|---|---|
pers | bytes | An optional personalization string used to add domain separation. |
Returns
Name | Type | Description |
---|---|---|
pk | Curve25519PublicKey | The Curve25519 public key. Useful for key exchange. |
sk | Curve25519SecretKey | The Curve25519 secret key. Pairs well with deriveSymmetricKey. |
deriveSymmetricKey
Derive a symmetric key from a pair of keys using x25519.
Precompile address
0x0100000000000000000000000000000000000002
Gas cost
100,000
Example
bytes32 publicKey = ... ;
bytes32 privateKey = ... ;
bytes32 symmetric = Sapphire.deriveSymmetricKey(publicKey, privateKey);
function deriveSymmetricKey(Curve25519PublicKey peerPublicKey, Curve25519SecretKey secretKey)
internal
view
returns (bytes32);
Parameters
Name | Type | Description |
---|---|---|
peerPublicKey | Curve25519PublicKey | The peer's public key. |
secretKey | Curve25519SecretKey | Your secret key. |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes32 | A derived symmetric key. |
encrypt
Encrypt and authenticate the plaintext and additional data using DeoxysII.
Precompile address
0x0100000000000000000000000000000000000003
Gas cost
50,000 minimum plus 100 per word of input
Example
bytes32 key = ... ;
bytes32 nonce = ... ;
bytes memory text = "plain text";
bytes memory ad = "additional data";
bytes memory encrypted = Sapphire.encrypt(key, nonce, text, ad);
bytes memory decrypted = Sapphire.decrypt(key, nonce, encrypted, ad);
function encrypt(bytes32 key, bytes32 nonce, bytes memory plaintext, bytes memory additionalData)
internal
view
returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
key | bytes32 | The key to use for encryption. |
nonce | bytes32 | The nonce. Note that only the first 15 bytes of this parameter are used. |
plaintext | bytes | The plaintext to encrypt and authenticate. |
additionalData | bytes | The additional data to authenticate. |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes | The ciphertext with appended auth tag. |
decrypt
Decrypt and authenticate the ciphertext and additional data using DeoxysII. Reverts if the auth tag is incorrect.
Precompile address
0x0100000000000000000000000000000000000004
Gas cost
50,000 minimum plus 100 per word of input
Example
bytes32 key = ... ;
bytes32 nonce = ... ;
bytes memory text = "plain text";
bytes memory ad = "additional data";
bytes memory encrypted = Sapphire.encrypt(key, nonce, text, ad);
bytes memory decrypted = Sapphire.decrypt(key, nonce, encrypted, ad);
function decrypt(bytes32 key, bytes32 nonce, bytes memory ciphertext, bytes memory additionalData)
internal
view
returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
key | bytes32 | The key to use for decryption. |
nonce | bytes32 | The nonce. Note that only the first 15 bytes of this parameter are used. |
ciphertext | bytes | The ciphertext with tag to decrypt and authenticate. |
additionalData | bytes | The additional data to authenticate against the ciphertext. |
Returns
Name | Type | Description |
---|---|---|
<none> | bytes | The original plaintext. |
generateSigningKeyPair
Generate a public/private key pair using the specified method and
seed. The available methods are items in the
Sapphire.SigningAlg
enum. Note, however, that the
generation method ignores subvariants, so all three Ed25519-based are
equivalent, and all Secp256k1 & Secp256r1 based methods are equivalent.
Sr25519 is not available and will return an error.
Precompile address
0x0100000000000000000000000000000000000005
Gas Cost
Ed25519: 1,000 gas
0
(Ed25519Oasis
)1
(Ed25519Pure
)2
(Ed25519PrehashedSha512
)
Secp256k1: 1,500 gas.
3
(Secp256k1Oasis
)4
(Secp256k1PrehashedKeccak256
)5
(Secp256k1PrehashedSha256
)
Secp256r1: 4,000 gas
7
(Secp256r1PrehashedSha256
)
Secp384r1: 18,000 gas
8
(Secp384r1PrehashedSha384
)
Key Formats
Ed25519
Public key: 32 bytes Secret key: 32 bytes
Secp256k1 & Secp256r1
Public key: 33 bytes, compressed format (0x02
or 0x03
prefix, then 32
byte X coordinate).
Secret key: 32 bytes
Secp384r1
Public key: 49 bytes, compressed format (0x02
or 0x03
prefix, then 48
byte X coordinate).
Secret key: 48 bytes
Example
bytes memory seed = hex"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
bytes memory publicKey;
bytes memory privateKey;
(publicKey, privateKey) = Sapphire.generateSigningKeyPair(Sapphire.SigningAlg.Ed25519Pure, seed);
function generateSigningKeyPair(SigningAlg alg, bytes memory seed)
internal
view
returns (bytes memory publicKey, bytes memory secretKey);
Parameters
Name | Type | Description |
---|---|---|
alg | SigningAlg | The signing alg for which to generate a keypair. |
seed | bytes | The seed to use for generating the key pair. You can use the randomBytes method if you don't already have a seed. |
Returns
Name | Type | Description |
---|---|---|
publicKey | bytes | The public part of the keypair. |
secretKey | bytes | The secret part of the keypair. |
sign
Sign a message within the provided context using the specified
algorithm, and return the signature. The context_or_digest
and
messages
parameters change in meaning slightly depending on the method
requested. For methods that take a context in addition to the message you
must pass the context in the context_or_digest
parameter and use
message
as expected. For methods that take a pre-existing hash of the
message, pass that in context_or_digest
and leave message
empty.
Specifically the Ed25519Oasis
and Secp256k1Oasis
variants take both a
context and a message (each are variable length bytes
), the context
serves as a domain separator.
Precompile address
0x0100000000000000000000000000000000000006
Gas cost
See below for the method-dependent base cost, plus 8 gas per 32 bytes of context and message except digest.
Signing algorithms
0
(Ed25519Oasis
): 1,500 gas, variable length context and message.1
(Ed25519Pure
): 1,500 gas, empty context, variable length message.2
(Ed25519PrehashedSha512
): 1,500 gas, pre-existing SHA-512 hash (64 bytes) as context, empty message.3
(Secp256k1Oasis
): 3,000 gas, variable length context and message4
(Secp256k1PrehashedKeccak256
): 3,000 gas, pre-existing hash (32 bytes) as context, empty message.5
(Secp256k1PrehashedSha256
): 3,000 gas, pre-existing hash (32 bytes) as context, empty message.7
(Secp256r1PrehashedSha256
): 9,000 gas, pre-existing hash (32 bytes) as context, empty message.8
(Secp384r1PrehashedSha384
): 43,200 gas, pre-existing hash (32 bytes) as context, empty message.
Example
Sapphire.SigningAlg alg = Sapphire.SigningAlg.Ed25519Pure;
bytes memory pk;
bytes memory sk;
(pk, sk) = Sapphire.generateSigningKeyPair(alg, Sapphire.randomBytes(32, ""));
bytes memory signature = Sapphire.sign(alg, sk, "", "signed message");
Note: see: @oasisprotocol/oasis-sdk :: precompile/confidential.rs :: call_sign
function sign(SigningAlg alg, bytes memory secretKey, bytes memory contextOrHash, bytes memory message)
internal
view
returns (bytes memory signature);
Parameters
Name | Type | Description |
---|---|---|
alg | SigningAlg | The signing algorithm to use. |
secretKey | bytes | The secret key to use for signing. The key must be valid for use with the requested algorithm. |
contextOrHash | bytes | Domain-Separator Context, or precomputed hash bytes. |
message | bytes | Message to sign, should be zero-length if precomputed hash given. |
Returns
Name | Type | Description |
---|---|---|
signature | bytes | The resulting signature. |
verify
Verifies that the provided digest was signed with using the
secret key corresponding to the provided private key and the specified
signing algorithm.
The method
, context_or_digest
and message
parameters have the same
meaning as described above in the sign() function.
Precompile address
0x0100000000000000000000000000000000000007
Gas cost
The algorithm-specific base cost below, with an additional 8 gas per
32 bytes of context
and message
for the Ed25519Oasis
,
Ed25519Pure
and Secp256k1Oasis
algorithms.
0
(Ed25519Oasis
): 2,000 gas1
(Ed25519Pure
): 2,000 gas2
(Ed25519PrehashedSha512
): 2,000 gas3
(Secp256k1Oasis
): 3,000 gas4
(Secp256k1PrehashedKeccak256
): 3,000 gas5
(Secp256k1PrehashedSha256
): 3,000 gas7
(Secp256r1PrehashedSha256
): 7,900 gas8
(Secp384r1PrehashedSha384
): 37,920 gas
Example
Sapphire.SigningAlg alg = Sapphire.SigningAlg.Secp256k1PrehashedKeccak256;
bytes memory pk;
bytes memory sk;
bytes memory digest = abi.encodePacked(keccak256("signed message"));
(pk, sk) = Sapphire.generateSigningKeyPair(alg, Sapphire.randomBytes(32, ""));
bytes memory signature = Sapphire.sign(alg, sk, digest, "");
require( Sapphire.verify(alg, pk, digest, "", signature) );
Note: see: @oasisprotocol/oasis-sdk :: precompile/confidential.rs :: call_verify
function verify(
SigningAlg alg,
bytes memory publicKey,
bytes memory contextOrHash,
bytes memory message,
bytes memory signature
) internal view returns (bool verified);
Parameters
Name | Type | Description |
---|---|---|
alg | SigningAlg | The signing algorithm by which the signature was generated. |
publicKey | bytes | The public key against which to check the signature. |
contextOrHash | bytes | Domain-Separator Context, or precomputed hash bytes |
message | bytes | The hash of the message that was signed, should be zero-length if precomputed hash was given. |
signature | bytes | The signature to check. |
Returns
Name | Type | Description |
---|---|---|
verified | bool | Whether the signature is valid for the given parameters. |
padGas
Set the current transactions gas usage to a specific amount
Will cause a reversion if the current usage is more than the amount.
Note: see: @oasisprotocol/oasis-sdk :: precompile/gas.rs :: call_pad_gas
function padGas(uint128 toAmount) internal view;
Parameters
Name | Type | Description |
---|---|---|
toAmount | uint128 | Gas usage will be set to this amount |
gasUsed
Returns the amount of gas currently used by the transaction
Note: see: @oasisprotocol/oasis-sdk :: precompile/gas.rs :: call_gas_used
function gasUsed() internal view returns (uint64);
Enums
SigningAlg
enum SigningAlg {
Ed25519Oasis,
Ed25519Pure,
Ed25519PrehashedSha512,
Secp256k1Oasis,
Secp256k1PrehashedKeccak256,
Secp256k1PrehashedSha256,
Sr25519,
Secp256r1PrehashedSha256,
Secp384r1PrehashedSha384
}
sha384
Hash the input data with SHA-384.
Notes:
-
standard: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
-
see: @oasisprotocol/oasis-sdk :: precompile/sha2.rs :: call_sha384
function sha384(bytes memory input) view returns (bytes memory output);
Parameters
Name | Type | Description |
---|---|---|
input | bytes | Bytes to hash. |
Returns
Name | Type | Description |
---|---|---|
output | bytes | 48 byte digest. |
sha512
Hash the input data with SHA-512, according to NIST.FIPS.180-4
Precompile address
0x0100000000000000000000000000000000000101
Warning: SHA-512 vs SHA-512/256 Length-Extension Attacks
SHA-512 is vulnerable to length-extension attacks, which are relevant if you are computing the hash of a secret message. The SHA-512/256 variant is not vulnerable to length-extension attacks.
Gas Cost
115 gas, then 13 gas per word
Example
bytes memory result = sha512(abi.encodePacked("input data"));
Notes:
-
standard: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
-
see: @oasisprotocol/oasis-sdk :: precompile/sha2.rs :: call_sha512
function sha512(bytes memory input) view returns (bytes memory output);
Parameters
Name | Type | Description |
---|---|---|
input | bytes | Bytes to hash. |
Returns
Name | Type | Description |
---|---|---|
output | bytes | 64 byte digest. |
sha512_256
Hash the input data with SHA-512/256, according to NIST.FIPS.180-4.
Precompile address
0x0100000000000000000000000000000000000102
Gas cost
115 gas, then 13 gas per word
Example
bytes32 result = sha512_256(abi.encodePacked("input data"));
Warning: SHA-512 vs SHA-512/256 Length-Extension Attacks
SHA-512 is vulnerable to length-extension attacks, which are relevant if you are computing the hash of a secret message. The SHA-512/256 variant is not vulnerable to length-extension attacks.
Notes:
-
standard: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
-
see: @oasisprotocol/oasis-sdk :: precompile/sha2.rs :: call_sha512_256
function sha512_256(bytes memory input) view returns (bytes32 result);
Parameters
Name | Type | Description |
---|---|---|
input | bytes | Bytes to hash. |
Returns
Name | Type | Description |
---|---|---|
result | bytes32 | 32 byte digest. |
ParsedSiweMessage
struct ParsedSiweMessage {
bytes schemeDomain;
address addr;
bytes statement;
bytes uri;
bytes version;
uint256 chainId;
bytes nonce;
bytes issuedAt;
bytes expirationTime;
bytes notBefore;
bytes requestId;
bytes[] resources;
}
SiweParser
Call parseSiweMsg() and provide the EIP-4361 SIWE message. The parser will generate the ParsedSiweMessage struct which you can then use to extract the authentication information in your on-chain contract.
Functions
_hexStringToAddress
Convert string containing hex address without 0x prefix to solidity address object.
function _hexStringToAddress(bytes memory s) internal pure returns (address);
_fromHexChar
function _fromHexChar(uint8 c) internal pure returns (uint8);
_substr
Substring.
function _substr(bytes memory str, uint256 startIndex, uint256 endIndex) internal pure returns (bytes memory);
_parseUint
String to Uint using decimal format. No error handling.
function _parseUint(bytes memory b) internal pure returns (uint256);
_parseField
Parse "NAME: VALUE" in str starting at index i and ending at \n or end of bytes.
function _parseField(bytes calldata str, string memory name, uint256 i) internal pure returns (bytes memory, uint256);
Returns
Name | Type | Description |
---|---|---|
<none> | bytes | VALUE and new i, if NAME matched; otherwise empty value and old i. |
<none> | uint256 |
_parseArray
Parse bullets, one per line in str starting at i.
function _parseArray(bytes calldata str, uint256 i) internal pure returns (bytes[] memory, uint256);
Returns
Name | Type | Description |
---|---|---|
<none> | bytes[] | Array of parsed values and a new i. |
<none> | uint256 |
parseSiweMsg
Parse SIWE message.
function parseSiweMsg(bytes calldata siweMsg) internal pure returns (ParsedSiweMessage memory);
Returns
Name | Type | Description |
---|---|---|
<none> | ParsedSiweMessage | ParsedSiweMessage struct with populated fields from the message. |
timestampFromIso
Parse RFC 3339 (ISO 8601) string to timestamp.
function timestampFromIso(bytes memory str) internal pure returns (uint256);
Errors
InvalidAddressLength
Invalid length of the hex-encoded address
error InvalidAddressLength();
InvalidNonce
Invalid length of the nonce
error InvalidNonce();
SubcallReceiptKind
enum SubcallReceiptKind {
Invalid,
Delegate,
UndelegateStart,
UndelegateDone
}
Subcall
Interact with Oasis Runtime SDK modules from Sapphire.
State Variables
CONSENSUS_DELEGATE
string private constant CONSENSUS_DELEGATE = "consensus.Delegate";
CONSENSUS_UNDELEGATE
string private constant CONSENSUS_UNDELEGATE = "consensus.Undelegate";
CONSENSUS_WITHDRAW
string private constant CONSENSUS_WITHDRAW = "consensus.Withdraw";
CONSENSUS_TAKE_RECEIPT
string private constant CONSENSUS_TAKE_RECEIPT = "consensus.TakeReceipt";
ACCOUNTS_TRANSFER
string private constant ACCOUNTS_TRANSFER = "accounts.Transfer";
CORE_CALLDATAPUBLICKEY
string private constant CORE_CALLDATAPUBLICKEY = "core.CallDataPublicKey";
CORE_CURRENT_EPOCH
string private constant CORE_CURRENT_EPOCH = "core.CurrentEpoch";
ROFL_IS_AUTHORIZED_ORIGIN
string private constant ROFL_IS_AUTHORIZED_ORIGIN = "rofl.IsAuthorizedOrigin";
SUBCALL
Address of the SUBCALL precompile
address internal constant SUBCALL = 0x0100000000000000000000000000000000000103;
Functions
subcall
Submit a native message to the Oasis runtime layer. Messages
which re-enter the EVM module are forbidden: evm.*
.
function subcall(string memory method, bytes memory body) internal returns (uint64 status, bytes memory data);
Parameters
Name | Type | Description |
---|---|---|
method | string | Native message type. |
body | bytes | CBOR encoded body. |
Returns
Name | Type | Description |
---|---|---|
status | uint64 | Result of call. |
data | bytes | CBOR encoded result. |
subcall_static
Submit a read-only native message to the Oasis runtime layer using STATICCALL.
Messages which re-enter the EVM module are forbidden: evm.*
.
function subcall_static(string memory method, bytes memory body)
internal
view
returns (uint64 status, bytes memory data);
Parameters
Name | Type | Description |
---|---|---|
method | string | Native message type. |
body | bytes | CBOR encoded body. |
Returns
Name | Type | Description |
---|---|---|
status | uint64 | Result of call. |
data | bytes | CBOR encoded result. |
_subcallWithToAndAmount
Generic method to call {to:address, amount:uint128}
.
function _subcallWithToAndAmount(string memory method, StakingAddress to, uint128 value, bytes memory token)
internal
returns (uint64 status, bytes memory data);
Parameters
Name | Type | Description |
---|---|---|
method | string | Runtime SDK method name ('module.Action'). |
to | StakingAddress | Destination address. |
value | uint128 | Amount specified. |
token | bytes |
Returns
Name | Type | Description |
---|---|---|
status | uint64 | Non-zero on error. |
data | bytes | Module name on error. |
consensusTakeReceipt
Returns a CBOR encoded structure, containing the following possible keys. All keys are optional:
- shares:
u128
- epoch:
EpochTime
- receipt:
u64
- amount:
u128
- error:
{module: string, code: u32}
Keys returned by specific subcalls
Delegate
will have theerror
orshares
keys.UndelegateStart
will have theepoch
andreceipt
keys.UndelegateDone
will have theamount
key.
function consensusTakeReceipt(SubcallReceiptKind kind, uint64 receiptId) internal returns (bytes memory);
Parameters
Name | Type | Description |
---|---|---|
kind | SubcallReceiptKind | 1 (Delegate ), 2 (UndelegateStart ) or 3 (UndelegateDone ) |
receiptId | uint64 | ID of receipt |
_decodeReceiptUndelegateStart
function _decodeReceiptUndelegateStart(bytes memory result) internal pure returns (uint64 epoch, uint64 endReceipt);
_decodeReceiptUndelegateDone
function _decodeReceiptUndelegateDone(bytes memory result) internal pure returns (uint128 amount);
_decodeReceiptDelegate
Decodes a 'Delegate' receipt.
function _decodeReceiptDelegate(uint64 receiptId, bytes memory result) internal pure returns (uint128 shares);
Parameters
Name | Type | Description |
---|---|---|
receiptId | uint64 | Previously unretrieved receipt. |
result | bytes | CBOR encoded {shares: u128}. |
consensusTakeReceiptDelegate
function consensusTakeReceiptDelegate(uint64 receiptId) internal returns (uint128 shares);
consensusTakeReceiptUndelegateStart
function consensusTakeReceiptUndelegateStart(uint64 receiptId) internal returns (uint64 epoch, uint64 endReceipt);
consensusTakeReceiptUndelegateDone
function consensusTakeReceiptUndelegateDone(uint64 receiptId) internal returns (uint128 amount);
consensusUndelegate
Start the undelegation process of the given number of shares from consensus staking account to runtime account.
function consensusUndelegate(StakingAddress from, uint128 shares) internal;
Parameters
Name | Type | Description |
---|---|---|
from | StakingAddress | Consensus address which shares were delegated to. |
shares | uint128 | Number of shares to withdraw back to us. |
consensusUndelegate
function consensusUndelegate(StakingAddress from, uint128 shares, uint64 receiptId) internal;
consensusDelegate
Delegate native token to consensus level.
function consensusDelegate(StakingAddress to, uint128 amount) internal returns (bytes memory data);
Parameters
Name | Type | Description |
---|---|---|
to | StakingAddress | Consensus address shares are delegated to. |
amount | uint128 | Native token amount (in wei). |
consensusDelegate
Delegate native token to consensus level. Requests that the
number of shares allocated can be retrieved with a receipt. The receipt
will be of ReceiptKind.DelegateDone
and can be decoded using
decodeReceiptDelegateDone
.
function consensusDelegate(StakingAddress to, uint128 amount, uint64 receiptId) internal returns (bytes memory data);
Parameters
Name | Type | Description |
---|---|---|
to | StakingAddress | Consensus address shares are delegated to. |
amount | uint128 | Native token amount (in wei). |
receiptId | uint64 | contract-specific receipt to retrieve result. |
consensusWithdraw
Transfer from an account in this runtime to a consensus staking account.
function consensusWithdraw(StakingAddress to, uint128 value) internal;
Parameters
Name | Type | Description |
---|---|---|
to | StakingAddress | Consensus address which gets the tokens. |
value | uint128 | Token amount (in wei). |
accountsTransfer
Perform a transfer to another account. This is equivalent of
payable(to).transfer(value);
.
function accountsTransfer(address to, uint128 value) internal;
Parameters
Name | Type | Description |
---|---|---|
to | address | Destination account. |
value | uint128 | native token amount (in wei). |
roflEnsureAuthorizedOrigin
Verify whether the origin transaction is signed by an authorized ROFL instance for the given application.
function roflEnsureAuthorizedOrigin(bytes21 appId) internal view;
Parameters
Name | Type | Description |
---|---|---|
appId | bytes21 | ROFL app identifier |
_parseCBORPublicKeyInner
function _parseCBORPublicKeyInner(bytes memory in_data, uint256 in_offset)
internal
pure
returns (uint256 offset, CallDataPublicKey memory public_key);
_parseCBORCallDataPublicKey
function _parseCBORCallDataPublicKey(bytes memory in_data)
internal
pure
returns (uint256 epoch, CallDataPublicKey memory public_key);
coreCallDataPublicKey
function coreCallDataPublicKey() internal view returns (uint256 epoch, CallDataPublicKey memory public_key);
coreCurrentEpoch
function coreCurrentEpoch() internal view returns (uint256);
Errors
SubcallError
Raised if the underlying subcall precompile does not succeed
error SubcallError();
ParseReceiptError
There was an error parsing the receipt
error ParseReceiptError(uint64 receiptId);
ConsensusUndelegateError
error ConsensusUndelegateError(uint64 status, string data);
ConsensusDelegateError
error ConsensusDelegateError(uint64 status, string data);
ConsensusTakeReceiptError
error ConsensusTakeReceiptError(uint64 status, string data);
ConsensusWithdrawError
error ConsensusWithdrawError(uint64 status, string data);
AccountsTransferError
error AccountsTransferError(uint64 status, string data);
WrongMapSizeError
Expected map of different size!
error WrongMapSizeError();
TakeReceiptKindOutOfRange
Unknown type of receipt!
error TakeReceiptKindOutOfRange(uint256 receiptKind);
RoflOriginNotAuthorizedForApp
The origin is not authorized for the given ROFL app
error RoflOriginNotAuthorizedForApp();
TokenNameTooLong
Name of token cannot be CBOR encoded with current functions
error TokenNameTooLong();
InvalidReceiptId
Invalid receipt ID
error InvalidReceiptId();
MissingKey
CBOR parser expected a key, but it was not found in the map!
error MissingKey();
IncompleteParse
We expected to have parsed everything, but there are excess bytes!
error IncompleteParse();
CoreCurrentEpochError
Error while trying to retrieve current epoch
error CoreCurrentEpochError(uint64);
CoreCallDataPublicKeyError
Error while trying to retrieve the calldata public key
error CoreCallDataPublicKeyError(uint64);
Structs
CallDataPublicKey
struct CallDataPublicKey {
bytes32 key;
bytes32 checksum;
bytes32[2] signature;
uint256 expiration;
}
WrappedROSE
Inherits: ERC20, ERC20Burnable
Functions
constructor
constructor() ERC20("Wrapped ROSE", "wROSE");
deposit
function deposit() external payable;
withdraw
function withdraw(uint256 amount) external;
receive
receive() external payable;
_deposit
function _deposit() internal;
Events
Deposit
event Deposit(address indexed dst, uint256 wad);
Withdrawal
event Withdrawal(address indexed src, uint256 wad);
hmac_sha512_256_memcpy
Copying key buffer failed (identity precompile error?)
error hmac_sha512_256_memcpy();
hmac_sha512_256
Implements HMAC using SHA512-256.
https://en.wikipedia.org/wiki/HMAC
function hmac_sha512_256(bytes memory key, bytes memory message) view returns (bytes32);
Parameters
Name | Type | Description |
---|---|---|
key | bytes | the secret key. |
message | bytes | the message to be authenticated. #### Example solidity bytes memory key = "arbitrary length key"; bytes memory message = "arbitrary length message"; bytes32 hmac = hmac_sha512_256(key, message) |
Constants
SHA512_256_BLOCK_SIZE
uint256 constant SHA512_256_BLOCK_SIZE = 128;
PRECOMPILE_IDENTITY_ADDRESS
uint256 constant PRECOMPILE_IDENTITY_ADDRESS = 4;
HMAC_IPAD
bytes32 constant HMAC_IPAD = 0x3636363636363636363636363636363636363636363636363636363636363636;
HMAC_OPAD_XOR_IPAD
bytes32 constant HMAC_OPAD_XOR_IPAD = 0x6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a;