- Download and install the OP_WALLET Chrome Extension.
- Set up the wallet and switch the network to Regtest.
- If you don't have any Regtest Bitcoin, get some from this faucet.
- Clone the OP_20 template contract repository:
git clone https://github.com/btc-vision/OP_20.git
This step is crucial for customizing your OP_20 token. You will need to adjust several key properties such as maxSupply
, decimals
, name
, and symbol
.
Here’s what each property means and how you can customize it:
maxSupply
:
- This defines the total supply of your token.
- It’s a
u256
value representing the maximum number of tokens that will ever exist. - The number should include the full number of decimals.
- Example: If you want a total supply of 1,000,000 tokens with 18 decimals, the value should be
1000000000000000000000000
.
const maxSupply: u256 = u128.fromString('1000000000000000000000000').toU256(); // 1,000,000 tokens with 18 decimals
decimals
:
- This property defines how divisible your token is.
- A value of
18
means the token can be divided down to 18 decimal places, similar to how Ethereum handles its tokens.
const decimals: u8 = 18; // Your decimals
name
:
- The
name
is a string representing the full name of your token. - This will be displayed in wallets and exchanges.
const name: string = 'YourTokenName'; // e.g., 'My Custom Token'
symbol
:
- The
symbol
is a short string representing the ticker symbol of your token. - Similar to how "BTC" represents Bitcoin.
const symbol: string = 'SYM'; // e.g., 'MYT'
Open the OP_20
template repository in your IDE or text editor and navigate to src/contracts/MyToken.ts
. Look for the following section in the onInstantiated
method:
const maxSupply: u256 = u128.fromString('1000000000000000000000000').toU256(); // Your max supply
const decimals: u8 = 18; // Your decimals
const name: string = 'YourTokenName'; // Your token name
const symbol: string = 'SYM'; // Your token symbol
Modify the values as needed for your token.
After customizing your token's properties, build the contract:
-
Open your terminal and navigate to the location of the downloaded
OP_20
template folder. -
Run the following commands:
npm install npm run build
-
After building, a
build
folder will be created in the root of theOP_20
folder. Look for[nameoftoken].wasm
for the compiled contract.
- Open the OP_WALLET extension and select the "deploy" option.
- Drag your
.wasm
file or click to choose it. - Send your transaction to deploy the token contract onto Bitcoin with OP_NET.
- Copy the token address from your OP_WALLET.
- Go to Motoswap and paste your token address into the top or bottom box.
- Enter the amount of tokens you wish to add to the liquidity pool.
- Select the other side of the liquidity pair (e.g., WBTC) and enter the amount of tokens you wish to add.
- Click "Add Liquidity".
Your token is now tradeable on Motoswap!
Now that you've set up the basic token properties, you can add additional functionality to your OP_20 token contract. Here are some common customizations:
To add custom functionality to your token, you can define new methods in your contract. For example, let's say you want to add an "airdrop" function that distributes tokens to multiple addresses.
public override callMethod(method: Selector, calldata: Calldata): BytesWriter {
switch (method) {
case encodeSelector('airdrop'):
return this.airdrop(calldata);
default:
return super.callMethod(method, calldata);
}
}
private airdrop(calldata: Calldata): BytesWriter {
const drops: Map<Address, u256> = calldata.readAddressValueTuple();
const addresses: Address[] = drops.keys();
for (let i: i32 = 0; i < addresses.length; i++) {
const address = addresses[i];
const amount = drops.get(address);
this._mint(address, amount);
}
const writer: BytesWriter = new BytesWriter(1);
writer.writeBoolean(true);
return writer;
}
You may want to override some of the existing methods in the DeployableOP_20
base class. For example, you might want to add additional logic when minting tokens.
protected _mint(to: Address, amount: u256): void {
super._mint(to, amount);
// Add custom logic here
Blockchain.log(`Minted ${amount.toString()} tokens to ${to.toString()}`); // Only work inside OP_NET Uint Test Framework
}
Events in OP_NET allow you to emit signals that external observers can listen to. These are useful for tracking specific actions within your contract, such as token transfers or approvals.
class TransferEvent extends NetEvent {
constructor(from: Address, to: Address, amount: u256) {
const writer = new BytesWriter(ADDRESS_BYTE_LENGTH + ADDRESS_BYTE_LENGTH + 32);
writer.writeAddress(from);
writer.writeAddress(to);
writer.writeU256(amount);
super('Transfer', writer);
}
}
class MyToken extends DeployableOP_20 {
public transfer(to: Address, amount: u256): void {
const from: Address = Blockchain.sender;
this._mint(to, amount);
this.emitEvent(new TransferEvent(from, to, amount));
}
}
If you want to add more control over who can call certain methods or add advanced features like pausing token transfers, you can implement access control mechanisms.
public mint(to: Address, amount: u256): void {
this.onlyOwner(Blockchain.sender); // Restrict minting to the contract owner
this._mint(to, amount);
}
- Solidity: The constructor runs only once at the time of contract deployment and is used for initializing contract state.
- AssemblyScript on OP_NET: The constructor runs every time the contract is instantiated. Use
onInstantiated()
for initialization that should occur only once.
- Solidity: Variables declared at the contract level are automatically persistent and are stored in the contract's state.
- AssemblyScript on OP_NET: Persistent state must be managed explicitly using storage classes like
StoredU256
,StoredBoolean
, andStoredString
.
- Solidity: Method selectors are built-in, and overriding them is straightforward.
- AssemblyScript on OP_NET: Method selectors are manually defined using functions like
encodeSelector()
, and method overriding is handled incallMethod
.
- Solidity: Events are declared and emitted using the
emit
keyword. - AssemblyScript on OP_NET: Events are custom classes derived from
NetEvent
and are emitted using theemitEvent
function.
The OPNet runtime allows you to implement complex logic in your token contract. For example, you can add functionality such as token freezing, custom transaction fees, or governance mechanisms.
These features are implemented by extending the base DeployableOP_20
or OP_20
class and overriding its methods as needed.
For more detailed explanations on specific topics related to the OPNet runtime, refer to the following documentation:
This project is licensed under the MIT License. View the full license here.