Skip to content

Commit bc628b4

Browse files
committed
Add timelock inspector getRoleMembers helper func
1 parent 728ec4d commit bc628b4

File tree

2 files changed

+83
-6
lines changed

2 files changed

+83
-6
lines changed

sdk/ton/inspector.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,15 @@ func (i *Inspector) GetRootMetadata(ctx context.Context, _address string) (types
8585

8686
var preOpCount *big.Int
8787
{
88-
rs, err := result.Slice(2)
88+
rs, err := result.Slice(0)
8989
if err != nil {
9090
return types.ChainMetadata{}, fmt.Errorf("error getting slice: %w", err)
9191
}
9292

93+
// skip two data points
94+
rs.LoadBigInt(256)
95+
rs.LoadAddr()
96+
9397
preOpCount, err = rs.LoadBigUInt(64)
9498
if err != nil {
9599
return types.ChainMetadata{}, fmt.Errorf("error getting preOpCount: %w", err)

sdk/ton/timelock_inspector.go

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ package ton
22

33
import (
44
"context"
5-
"errors"
65
"fmt"
76
"math/big"
87

98
"github.com/xssnick/tonutils-go/address"
109
"github.com/xssnick/tonutils-go/ton"
1110
"github.com/xssnick/tonutils-go/tvm/cell"
1211

12+
"github.com/smartcontractkit/chainlink-ton/pkg/bindings/mcms/timelock"
1313
"github.com/smartcontractkit/mcms/sdk"
1414
)
1515

@@ -50,24 +50,87 @@ func (i timelockInspector) GetMinDelay(ctx context.Context, _address string) (ui
5050
return rs.LoadUInt(64)
5151
}
5252

53+
// GetAdmins returns the list of addresses with the admin role
54+
func (i timelockInspector) GetAdmins(ctx context.Context, address string) ([]string, error) {
55+
return i.getRoleMembers(ctx, address, [32]byte(timelock.RoleAdmin.Bytes()))
56+
}
57+
5358
// GetProposers returns the list of addresses with the proposer role
5459
func (i timelockInspector) GetProposers(ctx context.Context, address string) ([]string, error) {
55-
return nil, errors.New("unimplemented")
60+
return i.getRoleMembers(ctx, address, [32]byte(timelock.RoleProposer.Bytes()))
5661
}
5762

5863
// GetExecutors returns the list of addresses with the executor role
5964
func (i timelockInspector) GetExecutors(ctx context.Context, address string) ([]string, error) {
60-
return nil, errors.New("unimplemented")
65+
return i.getRoleMembers(ctx, address, [32]byte(timelock.RoleExecutor.Bytes()))
6166
}
6267

6368
// GetBypassers returns the list of addresses with the bypasser role
6469
func (i timelockInspector) GetBypassers(ctx context.Context, address string) ([]string, error) {
65-
return nil, errors.New("unimplemented")
70+
return i.getRoleMembers(ctx, address, [32]byte(timelock.RoleBaypasser.Bytes()))
6671
}
6772

6873
// GetCancellers returns the list of addresses with the canceller role
6974
func (i timelockInspector) GetCancellers(ctx context.Context, address string) ([]string, error) {
70-
return nil, errors.New("unimplemented")
75+
return i.getRoleMembers(ctx, address, [32]byte(timelock.RoleCanceller.Bytes()))
76+
}
77+
78+
// GetOracles returns the list of addresses with the oracle role
79+
func (i timelockInspector) GetOracles(ctx context.Context, address string) ([]string, error) {
80+
return i.getRoleMembers(ctx, address, [32]byte(timelock.RoleOracle.Bytes()))
81+
}
82+
83+
// getRoleMembers returns the list of addresses with the given role
84+
func (i timelockInspector) getRoleMembers(ctx context.Context, _address string, role [32]byte) ([]string, error) {
85+
// Map to Ton Address type (timelock.address)
86+
addr, err := address.ParseAddr(_address)
87+
if err != nil {
88+
return nil, fmt.Errorf("invalid timelock address: %w", err)
89+
}
90+
91+
// TODO: mv and import from github.com/smartcontractkit/chainlink-ton/bindings/mcms/timelock
92+
block, err := i.client.CurrentMasterchainInfo(ctx)
93+
if err != nil {
94+
return nil, fmt.Errorf("failed to get current masterchain info: %w", err)
95+
}
96+
97+
_role, err := mapRoleParam(role)
98+
if err != nil {
99+
return nil, fmt.Errorf("failed to map opID param: %w", err)
100+
}
101+
102+
r, err := i.client.RunGetMethod(ctx, block, addr, "getRoleMemberCount", _role)
103+
if err != nil {
104+
return nil, fmt.Errorf("error getting getRoleMemberCount: %w", err)
105+
}
106+
107+
count, err := r.Int(0)
108+
if err != nil {
109+
return nil, fmt.Errorf("error decoding getRoleMemberCount result: %w", err)
110+
}
111+
112+
// For each address index in the roles count, get the address
113+
addresses := make([]string, 0, count.Uint64())
114+
for j := range count.Uint64() {
115+
rAddr, err := i.client.RunGetMethod(ctx, block, addr, "getRoleMember", _role, uint32(j))
116+
if err != nil {
117+
return nil, fmt.Errorf("error getting getRoleMember: %w", err)
118+
}
119+
120+
sAddr, err := rAddr.Slice(0)
121+
if err != nil {
122+
return nil, fmt.Errorf("error decoding getRoleMember result: %w", err)
123+
}
124+
125+
addr, err := sAddr.LoadAddr()
126+
if err != nil {
127+
return nil, fmt.Errorf("error decoding getRoleMember result slice: %w", err)
128+
}
129+
130+
addresses = append(addresses, addr.String())
131+
}
132+
133+
return addresses, nil
71134
}
72135

73136
func (i timelockInspector) IsOperation(ctx context.Context, _address string, opID [32]byte) (bool, error) {
@@ -203,3 +266,13 @@ func mapOpIDParam(opID [32]byte) (*cell.Slice, error) {
203266

204267
return b.EndCell().BeginParse(), nil
205268
}
269+
270+
// Help function to map (encode) role param to cell.Slice
271+
func mapRoleParam(role [32]byte) (*cell.Slice, error) {
272+
b := cell.BeginCell()
273+
if err := b.StoreBigUInt(new(big.Int).SetBytes(role[:]), 256); err != nil {
274+
return nil, fmt.Errorf("failed to store domain separator: %w", err)
275+
}
276+
277+
return b.EndCell().BeginParse(), nil
278+
}

0 commit comments

Comments
 (0)