Skip to content

Commit 64c27b5

Browse files
feat: implement issuance management and update related components
1 parent be34a6c commit 64c27b5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1433
-1194
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ test-contracts: ## Run the contracts tests
111111
.PHONY: bench
112112
bench: build ## Run benchmarks
113113
$(START_LOG)
114-
@forge test --root ./contracts --match-path "test/TestBaseLayerGas.t.sol" -vvv > perf/results/close-campaign-benchmark-base-layer.log 2>&1
115-
@pnpm run bench:close-campaign
114+
@forge test --root ./contracts --match-path "test/TestBaseLayerGas.t.sol" -vvv > perf/results/close-issuance-benchmark-base-layer.log 2>&1
115+
@pnpm run bench:close-issuance
116116
@echo "Benchmark completed! Check ./perf/results/ for details"
117117
$(END_LOG)
118118

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<i>A Linux-powered EVM rollup as a Debit Capital Market</i>
88
</div>
99
<div align="center">
10-
<b>Tokenized debt issuance through reverse campaign mechanism with collateralization</b>
10+
<b>Tokenized debt issuance through reverse auction mechanism with collateralization</b>
1111
</div>
1212
<br>
1313
<p align="center">

cmd/tribes-dcm/root/root.go

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,24 @@ import (
1010
"github.com/2025-2A-T20-G91-INTERNO/src/rollup/internal/infra/rollup"
1111
"github.com/rollmelette/rollmelette"
1212
"github.com/spf13/cobra"
13+
"github.com/spf13/viper"
1314
)
1415

1516
const (
1617
CMD_NAME = "dcm"
1718
)
1819

1920
var (
20-
cfg *configs.RollupConfig
21+
maxStartupTime int
22+
databaseUrl string
23+
adminAddress string
24+
adminAddressTest string
25+
verifierAddress string
26+
verifierAddressTest string
27+
badgeFactoryAddress string
28+
emergencyWithdrawAddr string
29+
safeErc1155MintAddress string
30+
cfg *configs.RollupConfig
2131
)
2232

2333
var Cmd = &cobra.Command{
@@ -28,6 +38,30 @@ var Cmd = &cobra.Command{
2838
}
2939

3040
func init() {
41+
// Rollup flags
42+
Cmd.Flags().IntVar(&maxStartupTime, "max-startup-time", 10, "Maximum startup time in seconds")
43+
cobra.CheckErr(viper.BindPFlag(configs.MAX_STARTUP_TIME, Cmd.Flags().Lookup("max-startup-time")))
44+
45+
// Database flags
46+
Cmd.Flags().StringVar(&databaseUrl, "database-url", "sqlite:///mnt/data/rollup.db", "SQLite database connection string")
47+
cobra.CheckErr(viper.BindPFlag(configs.DATABASE_URL, Cmd.Flags().Lookup("database-url")))
48+
49+
// Contracts flags
50+
Cmd.Flags().StringVar(&adminAddress, "admin-address", "", "Address of the admin user")
51+
cobra.CheckErr(viper.BindPFlag(configs.ADMIN_ADDRESS, Cmd.Flags().Lookup("admin-address")))
52+
53+
Cmd.Flags().StringVar(&verifierAddress, "verifier-address", "", "Address of the verifier contract")
54+
cobra.CheckErr(viper.BindPFlag(configs.VERIFIER_ADDRESS, Cmd.Flags().Lookup("verifier-address")))
55+
56+
Cmd.Flags().StringVar(&badgeFactoryAddress, "badge-factory-address", "", "Address of the badge factory contract")
57+
cobra.CheckErr(viper.BindPFlag(configs.BADGE_FACTORY_ADDRESS, Cmd.Flags().Lookup("badge-factory-address")))
58+
59+
Cmd.Flags().StringVar(&emergencyWithdrawAddr, "emergency-withdraw-address", "", "Address for emergency withdrawals")
60+
cobra.CheckErr(viper.BindPFlag(configs.EMERGENCY_WITHDRAW_ADDRESS, Cmd.Flags().Lookup("emergency-withdraw-address")))
61+
62+
Cmd.Flags().StringVar(&safeErc1155MintAddress, "safe-erc1155-mint-address", "", "Address for safe ERC1155 minting")
63+
cobra.CheckErr(viper.BindPFlag(configs.SAFE_ERC1155_MINT_ADDRESS, Cmd.Flags().Lookup("safe-erc1155-mint-address")))
64+
3165
Cmd.PreRunE = func(cmd *cobra.Command, args []string) error {
3266
var err error
3367
cfg, err = configs.LoadRollupConfig()
@@ -43,7 +77,7 @@ func run(cmd *cobra.Command, args []string) {
4377

4478
defer cancel()
4579

46-
repo, err := factory.NewRepositoryFromConnectionString(ctx, "sqlite:///mnt/data/rollup.db")
80+
repo, err := factory.NewRepositoryFromConnectionString(ctx, cfg.DatabaseUrl)
4781
if err != nil {
4882
slog.Error("Failed to initialize database", "error", err)
4983
os.Exit(1)

configs/generate/config.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
1+
#
2+
# Rollup
3+
#
4+
15
[rollup.MAX_STARTUP_TIME]
26
go-type = "Duration"
37
default = "10"
48
description = """Maximum startup time for the rollup service"""
59
used-by = ["rollup"]
610

11+
#
12+
# Database
13+
#
14+
15+
[database.DATABASE_URL]
16+
go-type = "string"
17+
default = "sqlite:///mnt/data/rollup.db"
18+
description = """SQLite database connection string"""
19+
used-by = ["rollup"]
720

821
#
922
# Contracts

configs/generated.go

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contracts/test/TestBaseLayerGas.t.sol

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,15 @@ contract TestBaseLayerGas is Test {
2929
paymentToken.mint(address(mockApplication), 1000000 * 10 ** 18);
3030
}
3131

32-
function testGasAddInputCloseCampaign() public {
32+
function testGasAddInputCloseIssuance() public {
3333
string memory payload =
34-
string(abi.encodePacked('{"path":"campaign/close","data":{"creator":"', _addressToString(creator), '"}}'));
34+
string(abi.encodePacked('{"path":"issuance/close","data":{"creator":"', _addressToString(creator), '"}}'));
3535

3636
uint256 gasBefore = gasleft();
3737
inputBox.addInput(address(mockApplication), bytes(payload));
3838
uint256 gasUsed = gasBefore - gasleft();
3939

40-
emit log_named_uint("Gas used (input close campaign):", gasUsed);
40+
emit log_named_uint("Gas used (input close issuance):", gasUsed);
4141

4242
assertEq(inputBox.getNumberOfInputs(address(mockApplication)), 1);
4343
}
@@ -64,11 +64,11 @@ contract TestBaseLayerGas is Test {
6464
assertEq(paymentToken.balanceOf(address(mockApplication)), initialAppBalance - raisedAmount);
6565
}
6666

67-
function testGasCloseCampaignAndWithdraw() public {
67+
function testGasCloseIssuanceAndWithdraw() public {
6868
uint256 raisedAmount = 100000 * 10 ** 18;
6969

7070
string memory closePayload =
71-
string(abi.encodePacked('{"path":"campaign/close","data":{"creator":"', _addressToString(creator), '"}}'));
71+
string(abi.encodePacked('{"path":"issuance/close","data":{"creator":"', _addressToString(creator), '"}}'));
7272

7373
uint256 gasInput = gasleft();
7474
inputBox.addInput(address(mockApplication), bytes(closePayload));

docs/configs.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ Address of the verifier contract, who can verify the social accounts
6666
* **Default:** `"0x0000000000000000000000000000000000000025"`
6767
* **Used by:** rollup
6868

69+
## `DATABASE_URL`
70+
71+
SQLite database connection string
72+
73+
* **Type:** `string`
74+
* **Default:** `"sqlite:///mnt/data/rollup.db"`
75+
* **Used by:** rollup
76+
6977
## `MAX_STARTUP_TIME`
7078

7179
Maximum startup time for the rollup service

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ require (
88
github.com/go-playground/validator/v10 v10.26.0
99
github.com/google/wire v0.6.0
1010
github.com/holiman/uint256 v1.3.2
11-
github.com/rollmelette/rollmelette v0.0.0-20250617235715-ae3ab2e9957f
11+
github.com/rollmelette/rollmelette v0.0.0-20251226042236-fcdb709c5635
1212
github.com/spf13/cobra v1.9.1
1313
github.com/spf13/viper v1.20.1
1414
github.com/stretchr/testify v1.10.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
6363
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
6464
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
6565
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
66-
github.com/rollmelette/rollmelette v0.0.0-20250617235715-ae3ab2e9957f h1:PYodwIxSWyE3DNHY++B7xPLL7qG1qSf9iEZ4s+4e0XI=
67-
github.com/rollmelette/rollmelette v0.0.0-20250617235715-ae3ab2e9957f/go.mod h1:vi9BDrdDsL59Qb+AsuxHktniuXZ68esNc/UJlgW5fOI=
66+
github.com/rollmelette/rollmelette v0.0.0-20251226042236-fcdb709c5635 h1:UpAdECibktivbj1ZNF+sanRCNFmdSdGacQAhC3oVzxk=
67+
github.com/rollmelette/rollmelette v0.0.0-20251226042236-fcdb709c5635/go.mod h1:vi9BDrdDsL59Qb+AsuxHktniuXZ68esNc/UJlgW5fOI=
6868
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
6969
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
7070
github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,21 @@ import (
99
)
1010

1111
var (
12-
ErrCampaignNotFound = errors.New("campaign not found")
13-
ErrInvalidCampaign = errors.New("invalid campaign")
12+
ErrIssuanceNotFound = errors.New("issuance not found")
13+
ErrInvalidIssuance = errors.New("invalid issuance")
1414
)
1515

16-
type CampaignState string
16+
type IssuanceState string
1717

1818
const (
19-
CampaignStateClosed CampaignState = "closed"
20-
CampaignStateOngoing CampaignState = "ongoing"
21-
CampaignStateCanceled CampaignState = "canceled"
22-
CampaignStateSettled CampaignState = "settled"
23-
CampaignStateCollateralExecuted CampaignState = "collateral_executed"
19+
IssuanceStateClosed IssuanceState = "closed"
20+
IssuanceStateOngoing IssuanceState = "ongoing"
21+
IssuanceStateCanceled IssuanceState = "canceled"
22+
IssuanceStateSettled IssuanceState = "settled"
23+
IssuanceStateCollateralExecuted IssuanceState = "collateral_executed"
2424
)
2525

26-
type Campaign struct {
26+
type Issuance struct {
2727
Id uint `json:"id" gorm:"primaryKey"`
2828
Title string `json:"title,omitempty" gorm:"not null"`
2929
Description string `json:"description,omitempty" gorm:"not null"`
@@ -37,16 +37,16 @@ type Campaign struct {
3737
MaxInterestRate *uint256.Int `json:"max_interest_rate,omitempty" gorm:"types:text;not null"`
3838
TotalObligation *uint256.Int `json:"total_obligation,omitempty" gorm:"types:text;not null;default:0"`
3939
TotalRaised *uint256.Int `json:"total_raised,omitempty" gorm:"types:text;not null;default:0"`
40-
State CampaignState `json:"state,omitempty" gorm:"types:text;not null"`
41-
Orders []*Order `json:"orders,omitempty" gorm:"foreignKey:CampaignId;constraint:OnDelete:CASCADE"`
40+
State IssuanceState `json:"state,omitempty" gorm:"types:text;not null"`
41+
Orders []*Order `json:"orders,omitempty" gorm:"foreignKey:IssuanceId;constraint:OnDelete:CASCADE"`
4242
ClosesAt int64 `json:"closes_at,omitempty" gorm:"not null"`
4343
MaturityAt int64 `json:"maturity_at,omitempty" gorm:"not null"`
4444
CreatedAt int64 `json:"created_at,omitempty" gorm:"not null"`
4545
UpdatedAt int64 `json:"updated_at,omitempty" gorm:"default:0"`
4646
}
4747

48-
func NewCampaign(title string, description string, promotion string, token types.Address, creatorAddress types.Address, collateralAddress types.Address, collateralAmount *uint256.Int, badgeAddress types.Address, debtIssued *uint256.Int, maxInterestRate *uint256.Int, closesAt int64, maturityAt int64, createdAt int64) (*Campaign, error) {
49-
campaign := &Campaign{
48+
func NewIssuance(title string, description string, promotion string, token types.Address, creatorAddress types.Address, collateralAddress types.Address, collateralAmount *uint256.Int, badgeAddress types.Address, debtIssued *uint256.Int, maxInterestRate *uint256.Int, closesAt int64, maturityAt int64, createdAt int64) (*Issuance, error) {
49+
issuance := &Issuance{
5050
Title: title,
5151
Description: description,
5252
Promotion: promotion,
@@ -57,57 +57,57 @@ func NewCampaign(title string, description string, promotion string, token types
5757
BadgeAddress: badgeAddress,
5858
DebtIssued: debtIssued,
5959
MaxInterestRate: maxInterestRate,
60-
State: CampaignStateOngoing,
60+
State: IssuanceStateOngoing,
6161
Orders: []*Order{},
6262
ClosesAt: closesAt,
6363
MaturityAt: maturityAt,
6464
CreatedAt: createdAt,
6565
}
66-
if err := campaign.validate(); err != nil {
66+
if err := issuance.validate(); err != nil {
6767
return nil, err
6868
}
69-
return campaign, nil
69+
return issuance, nil
7070
}
7171

72-
func (a *Campaign) validate() error {
72+
func (a *Issuance) validate() error {
7373
if a.Title == "" {
74-
return fmt.Errorf("%w: title cannot be empty", ErrInvalidCampaign)
74+
return fmt.Errorf("%w: title cannot be empty", ErrInvalidIssuance)
7575
}
7676
if a.Description == "" {
77-
return fmt.Errorf("%w: description cannot be empty", ErrInvalidCampaign)
77+
return fmt.Errorf("%w: description cannot be empty", ErrInvalidIssuance)
7878
}
7979
if a.Promotion == "" {
80-
return fmt.Errorf("%w: promotion cannot be empty", ErrInvalidCampaign)
80+
return fmt.Errorf("%w: promotion cannot be empty", ErrInvalidIssuance)
8181
}
8282
if a.Token == (types.Address{}) {
83-
return fmt.Errorf("%w: invalid token address", ErrInvalidCampaign)
83+
return fmt.Errorf("%w: invalid token address", ErrInvalidIssuance)
8484
}
8585
if a.CreatorAddress == (types.Address{}) {
86-
return fmt.Errorf("%w: invalid creator address", ErrInvalidCampaign)
86+
return fmt.Errorf("%w: invalid creator address", ErrInvalidIssuance)
8787
}
8888
if a.CollateralAddress == (types.Address{}) {
89-
return fmt.Errorf("%w: invalid collateral address", ErrInvalidCampaign)
89+
return fmt.Errorf("%w: invalid collateral address", ErrInvalidIssuance)
9090
}
9191
if a.CollateralAmount.Sign() == 0 {
92-
return fmt.Errorf("%w: collateral amount cannot be zero", ErrInvalidCampaign)
92+
return fmt.Errorf("%w: collateral amount cannot be zero", ErrInvalidIssuance)
9393
}
9494
if a.BadgeAddress == (types.Address{}) {
95-
return fmt.Errorf("%w: invalid badge address", ErrInvalidCampaign)
95+
return fmt.Errorf("%w: invalid badge address", ErrInvalidIssuance)
9696
}
9797
if a.DebtIssued.Sign() == 0 {
98-
return fmt.Errorf("%w: debt issued cannot be zero", ErrInvalidCampaign)
98+
return fmt.Errorf("%w: debt issued cannot be zero", ErrInvalidIssuance)
9999
}
100100
if a.MaxInterestRate.Sign() == 0 {
101-
return fmt.Errorf("%w: max interest rate cannot be zero", ErrInvalidCampaign)
101+
return fmt.Errorf("%w: max interest rate cannot be zero", ErrInvalidIssuance)
102102
}
103103
if a.CreatedAt == 0 {
104-
return fmt.Errorf("%w: creation date is missing", ErrInvalidCampaign)
104+
return fmt.Errorf("%w: creation date is missing", ErrInvalidIssuance)
105105
}
106106
if a.ClosesAt == 0 {
107-
return fmt.Errorf("%w: close date is missing", ErrInvalidCampaign)
107+
return fmt.Errorf("%w: close date is missing", ErrInvalidIssuance)
108108
}
109109
if a.MaturityAt == 0 {
110-
return fmt.Errorf("%w: maturity date is missing", ErrInvalidCampaign)
110+
return fmt.Errorf("%w: maturity date is missing", ErrInvalidIssuance)
111111
}
112112
return nil
113113
}

0 commit comments

Comments
 (0)