https://github.com/code-parth/memo-program-sbpf
https://github.com/code-parth/memo-program-sbpf
Last synced: 5 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/code-parth/memo-program-sbpf
- Owner: Code-Parth
- License: mit
- Created: 2025-10-25T22:15:13.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2025-10-26T00:28:42.000Z (5 months ago)
- Last Synced: 2025-10-26T01:06:02.290Z (5 months ago)
- Language: TypeScript
- Size: 10.7 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Solana Memo Program - sBPF Assembly
A Solana memo program written in pure sBPF assembly with type safety and test coverage.
## Overview
This project demonstrates how to build Solana programs directly in assembly language. The memo program accepts text messages and logs them to the blockchain, implemented in sBPF assembly.
## Features
- [x] **Pure sBPF Assembly** - Written directly in assembly
- [x] **No Signer Requirement** - Accepts 0+ accounts (matches official Solana Memo Program)
- [x] **Empty Memo Protection** - Rejects transactions with no memo text
- [x] **Type-Safe TypeScript** - type definitions with runtime validation
- [x] **Comprehensive Testing** - 7 test cases covering all scenarios
- [x] **Error Code Validation** - Typed error codes with human-readable messages
- [x] **Code Quality** - Proper error handling and edge case coverage
## Installation
1. **Clone the repository**
```bash
git clone https://github.com/Code-Parth/memo-program-sbpf.git
```
```bash
cd memo-program-sbpf
```
2. **Install dependencies**
```bash
yarn install
```
3. **Start local Solana validator** (in a separate terminal)
```bash
solana-test-validator
```
4. **Generate program keypair**
```bash
solana-keygen new --outfile deploy/memo-program-sbpf-keypair.json --force --no-passphrase
```
## Project Structure
```
memo-program-ts/
├── src/
│ └── memo-program-ts/
│ └── memo-program-ts.s # sBPF assembly source code
├── tests/
│ ├── types.ts # TypeScript type definitions
│ └── memo-program-sbpf.test.ts # Comprehensive test suite
├── deploy/
│ └── memo-program-sbpf-keypair.json # Program keypair (generated)
├── package.json # Node.js dependencies
├── tsconfig.json # TypeScript configuration
└── README.md # This file
```
## Usage
### Available Commands
```bash
# Compile the assembly program
sbpf build
# Deploy to local validator
sbpf deploy
# Run tests
sbpf test
# or
yarn test
# Build, deploy, and test in one command
sbpf e2e
```
### Quick Start Workflow
```bash
# 1. Start validator (separate terminal)
solana-test-validator
# 2. Build, deploy, and test
sbpf e2e
```
## How It Works
### Assembly Program Logic
The memo program (`src/memo-program-sbpf/memo-program-sbpf.s`) follows this flow:
1. **Read Account Count** - Load number of accounts from input buffer
2. **Fast Path Check** - If zero accounts, jump directly to instruction data
3. **Skip Accounts** - Efficiently iterate through accounts (real and duplicate) to reach instruction data
4. **Read Memo Data** - Extract instruction data length and pointer
5. **Validate Length** - Ensure memo is not empty (error 0x1 if empty)
6. **Log Memo** - Call `sol_log_` syscall to log the memo text
7. **Return Success** - Exit with code 0
### Memory Layout (Aligned BPF Format)
The program parses Solana's aligned BPF input buffer:
```
Offset 0x00: num_accounts (8 bytes)
For each account:
+0x00: marker (1 byte) - 0xFF for real, index for duplicate
+0x01: is_signer (1 byte)
+0x02: is_writable (1 byte)
+0x03: is_executable (1 byte)
+0x04: padding (4 bytes)
+0x08: pubkey (32 bytes)
+0x28: owner (32 bytes)
+0x48: lamports (8 bytes)
+0x50: data_len (8 bytes)
+0x58: data (data_len bytes)
+0x58+data_len: reserved (10,240 bytes) - MAX_PERMITTED_DATA_INCREASE
+0x58+data_len+10240: rent_epoch (8 bytes)
Total account size = 10,336 + data_len
After all accounts:
instruction_data_len (8 bytes)
instruction_data (variable bytes) - the memo text
```
### Key Insight: Account Size Calculation
The critical fix was calculating the correct account size:
```assembly
.equ MAX_PERMITTED_DATA_INCREASE, 10240
.equ ACCOUNT_FIXED_SIZE, 10336 # 88 + 10240 + 8
add64 r7, ACCOUNT_FIXED_SIZE # Add 10336
add64 r7, r3 # Add data_len
```
## Testing
### Test Suite
The project includes 7 comprehensive tests:
| # | Test Name | Description | Expected Result |
| --- | ------------------------- | ---------------------------------- | ------------------ |
| 1 | Valid memo with signer | Standard memo operation | ✅ Success |
| 2 | Memo without signer | No signer required (optimized) | ✅ Success |
| 3 | Empty memo | Zero-length instruction data | ❌ Error 0x1 |
| 4 | Long memo (256+ chars) | Large instruction data | ✅ Success |
| 5 | Multiple memos | 3 memos in one transaction | ✅ All logged |
| 6 | Multiple signers | 3 signers on one memo | ✅ Success |
| 7 | Type validation | TypeScript type safety checks | ✅ All types valid |
### Running Tests
```bash
# Run all tests
yarn test
# Run tests with sbpf (includes build & deploy)
sbpf e2e
```
## Error Codes
| Code | Hex | Name | Description |
| ---- | --- | --------- | ---------------------------------------- |
| 0 | 0x0 | Success | Transaction completed successfully |
| 1 | 0x1 | EmptyMemo | Instruction data is empty (no memo text) |
## Development
### Modifying the Assembly Program
1. Edit `src/memo-program-ts/memo-program-ts.s`
2. Rebuild: `sbpf build`
3. Deploy: `sbpf deploy`
4. Test: `yarn test`
### Adding New Tests
1. Open `tests/memo-program-sbpf.test.ts`
2. Add new test case:
```typescript
it("should handle your test case", async function () {
// Your test logic here
});
```
3. Run: `yarn test`
## Resources
### sBPF & Assembly
- [Blueshift sBPF Course](https://learn.blueshift.gg/en/courses/introduction-to-assembly/assembly-101)
- [Assembly Memo Challenge](https://learn.blueshift.gg/en/challenges/assembly-memo)
- [sBPF GitHub](https://github.com/blueshift-gg/sbpf)
### Solana Development
- [Solana Docs](https://docs.solana.com/)
- [Solana Cookbook](https://solanacookbook.com/)
- [BPF Loader Source](https://github.com/solana-labs/solana/tree/master/programs/bpf_loader)
### TypeScript & Testing
- [Mocha Documentation](https://mochajs.org/)
- [Chai Assertions](https://www.chaijs.com/)
- [TypeScript Handbook](https://www.typescriptlang.org/docs/)
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request
## License
This project is licensed under the [MIT License](https://github.com/Code-Parth/memo-program-sbpf?tab=MIT-1-ov-file).
## Acknowledgments
- Built with [sBPF](https://github.com/blueshift-gg/sbpf) by Blueshift
- Inspired by the [Blueshift Assembly Course](https://learn.blueshift.gg)
- Solana BPF loader serialisation format